题意:求(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;
}