10%的數據中,1 <= N <= 50;
20%的數據中,1 <= N <= 1000;
40%的數據中,1 <= N <= 100000;
100%的數據中,1 <= G <= 1000000000,1 <= N <= 1000000000。
傳說中的數論板子大合集,題面是真的好笑;
費馬小定理+CRT+lucas+快速冪+逆元+組合數,大概也就這么點吧;
題目要求mod p;
考慮冪很大我們用歐拉降冪:
a^b mod p =a^(b%phi(p)) mod p;
使用的條件是a,p互質且p為質數,這個是用費馬小定理搞的;
當a,p互質且p為質數,a^p mod p=a,所以a^(p-1) mod p=1;
所以a^b mod p= a^(b mod (p-1)) mod p;
用歐拉降冪的話phi(p)=p-1,所以是一樣的;
然后問題的關鍵在於求:
n有1e9,所以要用lucas求大組合數:
lucas定理:
然后模數不是質數,那么我們考慮常用的方法對每個質因子求一遍然后最后用CRT合並;
因為只有一次詢問,那么我們用sqrt(n)的復雜度枚舉n的每個因子,加到四個模線性方程組中,最后用CRT算出來;
記得注意各個部分的模數不同,lucas和算組合數的時候用prime,CRT的時候用p-1,最后快速冪的時候用p;
//MADE BY QT666 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int N=100050; const int Mod=999911659; int prime[]={2,3,4679,35617}; int n,g; ll Ans,sum[N]; ll qpow(ll x,ll y,ll mo){ ll ret=1; while(y){ if(y&1) (ret*=x)%=mo; (x*=x)%=mo;y>>=1; } return ret; } ll jc[10][N]; ll C(int n,int m,int x){ if(n<m) return 0; return jc[x][n]*qpow(jc[x][m],prime[x]-2,prime[x])%prime[x]*qpow(jc[x][n-m],prime[x]-2,prime[x])%prime[x]; } ll lucas(int n,int m,int x){ if(m==0) return 1; return C(n%prime[x],m%prime[x],x)*lucas(n/prime[x],m/prime[x],x)%prime[x]; } void Crt(){ for(int i=0;i<4;i++){ ll M=(Mod-1)/prime[i]; (Ans+=sum[i]*M%(Mod-1)*qpow(M,prime[i]-2,prime[i])%(Mod-1))%=(Mod-1); } } void work(int d){ for(int i=0;i<4;i++) (sum[i]+=lucas(n,d,i))%=prime[i]; } int main(){ scanf("%d%d",&n,&g);if(g==999911659) {puts("0");return 0;} for(int i=0;i<4;i++){ jc[i][0]=1; for(int j=1;j<=50000;j++) jc[i][j]=(jc[i][j-1]*j)%prime[i]; } g%=Mod; for(int i=1;i*i<=n;i++){ if(n%i==0){ if(i*i==n) work(i); else work(i),work(n/i); } } Crt(); printf("%lld\n",qpow(g,Ans,Mod)); return 0; }
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。