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
     来自:
  • 相关阅读:
    vue-awesome-swiper-T 轮播图
    transition-T 手机端滑动验证
    VUE-T
    跨域配置-Access-Control-Allow-Origin
    HTML中CSS引入图片并铺满背景
    mysql_affected_rows()、mysql_fetch_row、mysql_fetch_assoc
    tp框架的四种路由方式
    sql注入
    禁用cookie,怎么获得session
    git解决冲突的方法
  • 原文地址:https://www.cnblogs.com/maijing/p/4649441.html
Copyright © 2011-2022 走看看