bzoj 1951 [Sdoi2010]古代豬文
阿新 • • 發佈:2018-11-06
這是一道數論集合題
求式子,首先可以先用尤拉定理將式子降冪為指數mod (999911659-1)。
而對於指數可以在根號n的時間內列舉每個約數,對於每個約數求相應的組合數,可以用lucas定理來求解,
但是因為這個模數不是指數,所以把這個模數拆開,再用中國剩餘定理合併就好了
注意的點是當g等於999911659時,這個定理不適用,但顯然答案是0,所以要特判掉。
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define mode 999911658 using namespace std; typedef long long ll; ll n,g,x,y; ll mod[5]={0,2,3,4679,35617}; ll niv[5][40005],jc[5][40005],ans[5],tot; void gett(int u) { niv[u][1]=1; for(int i=2;i<mod[u];i++) { niv[u][i]=(mod[u]-mod[u]/i)*niv[u][mod[u]%i]%mod[u]; } jc[u][0]=1; for(int i=1;i<mod[u];i++) { jc[u][i]=jc[u][i-1]*i%mod[u]; } niv[u][0]=1; for(int i=1;i<mod[u];i++) { niv[u][i]=niv[u][i-1]*niv[u][i]%mod[u]; } } ll exgcd(ll a,ll b) { if(b==0) { x=1,y=0; return a; } ll r=exgcd(b,a%b); ll t=x; x=y; y=t-a/b*x; return r; } ll Lucas(ll x,ll y,int u) { if(x==0)return 1; if(y%mod[u]<x%mod[u])return 0; return Lucas(x/mod[u],y/mod[u],u)%mod[u]*jc[u][y%mod[u]]%mod[u]*niv[u][x%mod[u]]%mod[u]*niv[u][((y-x)%mod[u]+mod[u])%mod[u]]%mod[u]; } ll crt(int u) { ll as=0; for(int i=1;i<=4;i++) { ans[i]=Lucas(u,n,i); ll gg=exgcd(mode/mod[i],mod[i]); ans[i]/=gg; x=(x%mod[i]+mod[i])%mod[i]; x*=ans[i]%mode;x%=mode; as+=x*mode/mod[i]%mode; as%=mode; } return as; } void ys(ll u) { for(ll i=1;i*i<=u;i++) { if(u%i==0) { tot+=crt(i)%mode; tot%=mode; if(i*i==u)continue; tot+=crt(u/i)%mode; tot%=mode; } } } ll ksm(ll x,ll y) { ll as=1; while(y) { if(y%2==1) { as=as*x%(mode+1); } x=x*x%(mode+1); y=y/2; } return as; } int main() { scanf("%lld%lld",&n,&g); if(g==mode+1) { printf("0"); return 0; } for(int i=1;i<=4;i++)gett(i); ys(n); printf("%lld",ksm(g,tot)%(mode+1)); return 0; }