zoukankan      html  css  js  c++  java
  • 刷题总结——分糖(ssoj 容斥原理+逆元+快速幂+组合数求插板)

    题目:

    题目描述

    有 N 个(相同的)糖果,M 个(不同的)小朋友。M 和 N 满足:1≤M≤N≤100000(105)。
    要求:
    1.每个小朋友都至少有一个糖果。
    2.不存在正整数 X(X>=2),使得每个小朋友的糖果数都是 X 的倍数。
    3.糖果不能剩余。
    求分糖方法总数。答案模 1000000007(109+7)

    输入格式

    第一行为数据组数:T<=100000。
    接下来 N 行,每行 2 个如上文所示的正整数 N,M。

    输出格式

    输出 T 行,每行一个整数,为答案。
    注意取模!

    样例数据 1

    输入  [复制]

     

    6 2 
    7 2 
    6 3 
    6 4 
    7 4

    输出




    10 
    20

    备注

    【数据范围】
    对于 30% 的数据:1<=M<=N<=20
    对于 60% 的数据:1<=M<=N<=1000
    对于 100% 的数据:1<=M<=N<=100000

    题解:

      一道题充分证明我在数论上是个sb

      首先第一次学到用dfs来求充斥,涨姿势了····

      然后就是用组合数来解决将x个糖分到y个小朋友手里的问题····相当于在x-1个空格中插入y-1个板子···转化成组合数···

      最后一个问题就是组合数每次肯定只能通过预处理的阶乘相处来求··然而阶乘已经取模···相当于如何计算a/bmodp的问题····

      不难想到a/b相当于a*1/b,而1/b%p就是b模p的逆元····且p为质数的情况下逆元直接等于b的p-2次方模p,用快速幂来求即可

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=1e5+5;
    const int mod=1e9+7;
    vector<int>zhiyinzi[N];
    long long jc[N],T,n,m,ans,niyuan[N];
    bool notprime[N];
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline long long ksm(long long a,long long b)
    {
      long long temp=1;
      while(b)
      {
        if(b%2==1)  temp=(temp*a)%mod;
        b/=2;
        a=(a*a)%mod;
      }
      return temp;
    }
    inline void pre()
    {
      for(int i=2;i<=100000;i++)
      {
        if(!notprime[i])
        {
          zhiyinzi[i].push_back(i);  
          for(int j=2;j*i<=100000;j++)
          {  
            notprime[i*j]=true;
            zhiyinzi[i*j].push_back(i);
          }
        }
      }
      jc[0]=1;  
      for(int i=1;i<=100000;i++)  jc[i]=(jc[i-1]*i)%mod; 
      for(int i=0;i<=100000;i++)  niyuan[i]=ksm(jc[i],mod-2);
    }
    inline int calc(int a,int b)
    {
      if(a<b)  return 0;
      return ((long long)(jc[a-1]*niyuan[b-1])%mod*niyuan[a-b])%mod;
    }
    inline void dfs(int u,int tot,int f)
    {
      if(u==zhiyinzi[n].size())
      {
        ans=(ans+f*calc(n/tot,m))%mod;
        return;
      }
      dfs(u+1,tot*zhiyinzi[n][u],-f);
      dfs(u+1,tot,f);
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      pre();T=R();
      while(T--)  {
        ans=0;n=R(),m=R();
        dfs(0,1,1);
        cout<<(((ans%mod)+mod)%mod)<<endl;
      }
      return 0;
    }

      

  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/AseanA/p/7634532.html
Copyright © 2011-2022 走看看