0.0
刷的最后一道数论题,喔,一声长叹~
Link
今天还是来大致描述一下题面好了
给定(q,n(1≤q,n≤10^9)),计算 (q^{sum_{d|n}C^d_n}mod 999911659)
Solve
先考虑特殊情况,如果 (q)是(999911659)的倍数,则答案为(0),否则,因为(999911659)是质数,所以(q,n)互质。由欧拉定理的推论得:
[q^{sum_{d|n}C^d_n} equiv q^{sum_{d|n}C^d_n ext{mod 999911659}} ( ext{mod 999911659})
]
因此,我们计算 (q^{sum_{d|n}C^d_n ext{mod 999911659}})
尝试分解质因数 $999911659=2 ast 3 ast 4679 ast 35617 $。
然后枚举(n)的约数(d),运用(Lucas)定理求出组合数(C^d_n)。分别计算出(sum_{d|n}C^d_n)对(2,3,4679,35617)四个质数取摸的结果,记为(a_1,a_2,a_3,a_4)。
最后用中国剩余定理求解线性同余方程组:
(egin{cases} ext{x mod 2}=a_1\ ext{x mod 3}=a_2\ ext{x mod 4679}=a_3\ ext{x mod 35617}=a_4\end{cases})
即可得到(sum_{d|n}C^d_n ext{mod 999911659})的最小非负整数解 (x)。再用快速幂求出 (q^x)即可得到原问题的答案。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=999911658;
LL n,G,Fc[50005],a[5],b[5]={0,2,3,4679,35617},val;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
LL Pow(LL a,LL b,LL p){
LL w=a,s=1;
while(b){
if(b&1)s=w*s%p;
w=w*w%p;
b>>=1;
}
return s;
}
void make_Fc(LL p){
Fc[0]=1;
for(int i=1;i<=p;i++)Fc[i]=Fc[i-1]*i%p;
return ;
}
LL C(LL n,LL m,LL p){
if(n<m)return 0;
return Fc[n]*Pow(Fc[m],p-2,p)%p*Pow(Fc[n-m],p-2,p)%p;
}
LL Lucas(LL n,LL m,LL p){
if(n<m)return 0;if(!n)return 1;
return Lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
void CRT(){
for(int i=1;i<=4;i++)
val=(val+a[i]*(mod/b[i])%mod*Pow(mod/b[i],b[i]-2,b[i]))%mod;
}
int main(){
// freopen("P2480.in","r",stdin);
// freopen("P2480.out","w",stdout);
n=read();G=read();
if(G%(mod+1)==0){printf("0
");return 0;}
for(int k=1;k<=4;k++){
make_Fc(b[k]);
for(int i=1;i*i<=n;i++){
if(n%i==0){
a[k]=(a[k]+Lucas(n,i,b[k]))%b[k];
if(i*i!=n){
a[k]=(a[k]+Lucas(n,n/i,b[k]))%b[k];
}
}
}
}
CRT();
printf("%lld
",Pow(G,val,mod+1));
return 0;
}