zoukankan      html  css  js  c++  java
  • [SDOI2010]古代猪文

    洛咕

    题意:求(m^{sum{d|n C_n^d}} mod 999911659)

    分析:因为(999911659)是质数,则由欧拉定理的推论得(m^{sum{d|n C_n^d mod 999911658}} mod 999911659)

    因为(m^{sum{d|n C_n^d mod 999911658}})直接(Lucas)还是会爆,考虑将(999911658)质因数分解为(2*3*4679*35617),则可以运用(Lucas)定理分别求出(sum {d|n C_n^d} mod 2/3/4679/35617),记为(b_1,b_2,b_3,b_4)

    然后考虑合并.我们现在得到这样一个式子:

    (left{egin{aligned}xequiv b_1(mod 2) quad\ xequiv b_2(mod 3) quad\ xequiv b_3(mod 4679) quad\xequiv b_4(mod 35617) quadend{aligned} ight.)

    直接中国剩余定理求解(x)就行了.最后输出(m^x mod 999911658)

    综上我们需要用到Lucas定理(包括组合数,阶乘,逆元),中国剩余定理(包括扩欧)

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read(){
        LL s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    const LL mod=999911659;
    LL n,m,ans,tot;
    int prime[5]={0,2,3,4679,35617};
    LL a[50005],b[5],jc[50005];
    inline LL ksm(int a,int b,int c){
        LL cnt=1;
        while(b){
        	if(b&1)cnt=(1LL*cnt*a)%c;
        	a=(1LL*a*a)%c;
        	b>>=1;
        }
        return cnt;
    }
    inline void get_jc(int p){//计算组合数要用到阶乘
        jc[0]=1;
        for(int i=1;i<=p;i++)
        	jc[i]=(jc[i-1]*i)%p;
    }
    inline LL C(int n,int m,int p){//计算组合数
        if(n<0||m<0||n<m)return 0;
        return ((1LL*jc[n]*ksm(jc[m],p-2,p))%p*ksm(jc[n-m],p-2,p))%p;
    //直接根据费马小定理 用快速幂算逆元
    }
    inline LL Lucas(int n,int m,int p){//Lucas模板
        if(n<m)return 0;else if(n==0||m==0)return 1;
        return (1LL*C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
    }
    inline int exgcd(int a,int b,int &x,int &y){
        if(b==0){x=1;y=0;return a;}
        int d=exgcd(b,a%b,y,x);
        y-=x*(a/b);
        return d;
    }//中国剩余定理要用到扩欧
    inline void Intchina(){//中国剩余定理模板
        LL M=1;
        for(int i=1;i<=4;i++)M*=prime[i];
        for(int i=1;i<=4;i++){
        	int Mi=M/prime[i],x,y;
        	exgcd(Mi,prime[i],x,y);
        	ans=((ans+Mi*x*b[i])%M+M)%M;
        }
    }
    int main(){
        n=read();m=read();
        if(m%mod==0){puts("0");return 0;}//一定要特判
        for(int i=1;i*i<=n;i++){//枚举n的所有约数
        	if(n%i==0){
    	    	a[++tot]=i;
    	    	if(i*i!=n)a[++tot]=n/i;
            }
        }
    //分别计算mod 2 3 4679 35617的值
        for(int i=1;i<=4;i++){
        	get_jc(prime[i]);
        	for(int j=1;j<=tot;j++)
    	    b[i]=(b[i]+Lucas(n,a[j],prime[i]))%prime[i];
        }
        Intchina();//合并
        printf("%lld
    ",ksm(m,ans,mod));
        return 0;
    }
    
    
  • 相关阅读:
    HEOI2017游记
    uoj228:基础数据结构练习题
    bzoj1494【Noi2007】生成树计数
    bzoj1975【Sdoi2010】魔法猪学院
    bzoj2957:楼房重建
    uoj169:元旦老人与数列
    bzoj2178:圆的面积并
    一道好题
    Codeforces Round #440(Div.2)
    Codeforces Round #439 (Div. 2)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10628163.html
Copyright © 2011-2022 走看看