zoukankan      html  css  js  c++  java
  • C(m,n)%P

    program1 n!%P(P为质数)

    我们发现n! mod P的计算过程是以P为周期的的,举例如下:
    n = 10, P = 3
    n! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
        = 1 * 2 *
           4 * 5 *
           7 * 8 *
          10 *
          3 * 6 * 9
       = (1 * 2)^3 *
          1*
          3^3 * (1 * 2 * 3)
    最后一步中的1 * 2 *3可递归处理。
    因为P的倍数与P不互质,所以P的倍数不能直接乘入答案,应当用一个计数器变量g来保存答案中因子P的个数。
    我们提前预处理出fac[i] = 1 * 2 * 3 * … * (i – 1) * i mod P,函数calcfac(n)返回n! mod P的值,power(a, b, c)返回ab mod c的值,注意,calcfac(n)算出来的值不包含因子P,我们另外把因子P的个数另外存在g中。
    代码如下:
    typedef long long LL;
    LL calcfac(LL n)
    {
    if (n < P) return fac[n];
    LL s = n / P, t = n % P;
    LL res = power(fac[P - 1], s, P); //fac[P - 1]重复出现了s次
    res = res * fac[t] % P; //除去s次fac[P – 1]外,剩下的零头
    g += n / P; //提出n / P个因子P
    res = res* calcfac(n / P) % P; //递归处理
    return res;
    }
    program2 C(m,n)%P(P为质数)
    运用program1,算出m!%P,n!%P和(m-n)!%P,已知这三者的答案中因子P的个数为g1,g2,g3。
    我们可以得到:
    C(m,n)P - maijing3007 - maijing
     我们不假思索地认为g1-g2-g3>=0(否则C(m,n)算出来就是分数了),而且容易知道calcfac(n)*falcfac(m-n)与P互质(我们除去了P因子)所以可以变成:
    C(m,n)P - maijing3007 - maijing
     这样就可以直接算了。
     
    program3 C(m,n)%P(P不一定为质数)
    基本思路与program2相同。
    对P进行质因数分解,得到P = p1c1 * p2c2 * … * ptct。
    对于每个1≤i≤t,以pici为模运行program2,最后用中国剩余定理合并。这里pici不一定为质数,不过只需对原算法稍加修改即可。令modi = pici,fac[i] = 除去pi的倍数外i的阶乘。例如pi = 3,ci = 2,那么fac[10] = 1 * 2 * 4 * 5 * 7 * 8 * 10,除去了3的倍数3、6和9。阶乘依然是以modi为周期的,calcfac(n)与program2主体相同,只是统计因子个数时,应使用ret += n / pi而不是ret += n / modi,递归处理时也应该是calcfac(n / pi)而不是calcfac(n / modi)。
    当然,这个算法也有些局限,因为要求fac数组,所以pici要比较小,如果P是一个大质数就不行了。
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b) for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int dblcmp(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    
    inline void SetOpen(string s)
    {
    freopen((s+".in").c_str(),"r",stdin);
    freopen((s+".out").c_str(),"w",stdout);
    }
    
    inline int Getin_Int()
    {
    int res=0,flag=1;char z;
    for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
    if(z==EOF)return 0;
    if(z=='-'){flag=-flag;z=getchar();}
    for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
    return res*flag;
    }
    inline LL Getin_LL()
    {
    LL res=0,flag=1;char z;
    for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
    if(z==EOF)return 0;
    if(z=='-'){flag=-flag;z=getchar();}
    for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
    return res*flag;
    }
    
    const LL maxpici=100000;
    const LL maxcnt=100;
    
    LL n,m,P;
    LL cnt,p[maxcnt+10],c[maxcnt+10],mod[maxcnt+10],euler[maxcnt+10],fac[maxcnt+10][maxpici+10];
    LL ans;
    
    inline LL power(LL a,LL b,LL Mod)
    {
    LL x=1,y=a;
    while(b!=0){if(b&1)x=x*y%Mod;if(b==1)break;y=y*y%Mod;b/=2;}
    return x;
    }
    
    inline LL calfac(LL N,LL id,LL &g)
    {
    if(N<p[id])return fac[id][N];
    LL s=N/mod[id],t=N%mod[id],res=1;
    res=res*power(fac[id][mod[id]-1],s,mod[id])%mod[id];
    res=res*fac[id][t]%mod[id];
    g+=N/p[id];
    res=res*calfac(N/p[id],id,g)%mod[id];
    return res;
    }
    
    inline LL solve(LL id)
    {
    LL g1=0,g2=0,g3=0;
    LL fenzi=calfac(m,id,g1),fenmo=calfac(n,id,g2)*calfac(m-n,id,g3)%mod[id];
    return fenzi*power(fenmo,euler[id]-1,mod[id])%mod[id]*power(p[id],g1-g2-g3,mod[id])%mod[id];
    }
    
    inline void extend_gcd(LL a,LL &x,LL b,LL &y)
    {
    if(b==0){x=1;y=0;return;}
    LL dx,dy;
    extend_gcd(b,dx,a%b,dy);
    x=dy;
    y=dx-a/b*dy;
    }
    
    int main()
    {
    SetOpen("program");
    LL i,j,temp;
    m=Getin_Int();n=Getin_Int();P=Getin_Int();
    if(m<n){puts("0
    ");return 0;}
    temp=P;
    re(i,2,maxpici)if(temp%i==0)
    {
    ++cnt;
    p[cnt]=i;
    mod[cnt]=1;
    while(temp%i==0){c[cnt]++;mod[cnt]*=i;temp/=i;}
    euler[cnt]=mod[cnt]/p[cnt]*(p[cnt]-1);
    fac[cnt][0]=1;
    re(j,1,mod[cnt]-1)fac[cnt][j]=(j%p[cnt]==0)?fac[cnt][j-1]:fac[cnt][j-1]*j%mod[cnt];
    }
    ans=0;
    re(i,1,cnt)
    {
    temp=solve(i);
    LL a=P/mod[i],x,b=mod[i],y;
    extend_gcd(a,x,b,y);
    ans=(ans+temp*a%P*x%P)%P;
    }
    ans=(ans%P+P)%P;
    cout<<ans<<endl;
    return 0;
    }
    View Code
     来自:
  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/maijing/p/4649441.html
Copyright © 2011-2022 走看看