BZOJ 1951 Lucas定理+CRT

思路:

枚举约数

套个裸的Lucas+CRT就完了...

//By SiriusRen
#include <cmath>
#include <cstdio>
using namespace std;
#define int long long
const int M=999911658,N=35617;
void exgcd(int a,int b,int &x,int &y){
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,x,y);
    int temp=x;x=y;y=temp-a/b*y;
}
int CRT(int *a,int *m,int num){
    int ans=0;
    for(int i=1;i<=num;i++){
        int x,y;
        exgcd(M/m[i],m[i],x,y);
        ans=(ans+M/m[i]*x%M*a[i])%M;
    }return ans;
}
int power(int x,int y){
    int ans=1;
    while(y){
        if(y&1)ans=ans*x%(M+1);
        x=x*x%(M+1),y>>=1;
    }return ans;
}
int m[5]={0,2,3,4679,35617},n,g,fac[N],inv[N],sqr,s[N],top,ans[5],T;
int C(int x,int y){
    if(x<y)return 0;
    if(x<m[T]&&y<m[T])return fac[x]*inv[y]%m[T]*inv[x-y]%m[T];
    return C(x/m[T],y/m[T])*C(x%m[T],y%m[T])%m[T];
}
signed main(){
    scanf("%lld%lld",&n,&g),sqr=sqrt(n);
    for(int i=1;i<sqr;i++)if(n%i==0)s[++top]=i,s[++top]=n/i;
    if(sqr*sqr==n)s[++top]=sqr;
    if(n%sqr==0&&sqr*sqr!=n)s[++top]=sqr,s[++top]=n/sqr;
    fac[1]=fac[0]=inv[1]=inv[0]=1;
    for(T=1;T<=4;T++){
        for(int i=2;i<m[T];i++)fac[i]=fac[i-1]*i%m[T];
        for(int i=2;i<m[T];i++)inv[i]=(m[T]-m[T]/i)*inv[m[T]%i]%m[T];
        for(int i=2;i<m[T];i++)inv[i]=inv[i]*inv[i-1]%m[T];
        for(int i=1;i<=top;i++)ans[T]=(ans[T]+C(n,s[i]))%m[T];
    }
    printf("%lld\n",power(g,CRT(ans,m,4)+M));
}

 

posted @ 2017-03-15 21:12  SiriusRen  阅读(203)  评论(0编辑  收藏  举报