传送门
Description
给定两个数(N)、(G) ((N,Gleq 10^9)),求
[ans=G^{sum_{d|N} binom{N}{d}} (mod 999911659) ]
Solution
- 运用欧拉定理,所以指数只需要$sum_{d|N} binom{N}{d} mod 999911658 $
- 运用(Lucas)定理,( binom{m}{n} equiv binom{m/p}{n/p} binom{m\%p}{n\%p} mod p),其中(p)是个质数
- 但是(999911658)并不是个质数,不能用(Lucas)定理。这时我们把它分解:(999911658=2*3*4679*35617),对这(4)个质因子分别求解出它的答案(X[i]),原问题转化成一个解线性方程组的问题,因为(999911658)比较小,所以直接用中国剩余定理即可解决。
[G的指数=sum X[i] left ( frac{M}{p_i} ight )^{-1}_{p_i} frac{M}{m_i} ]
Code
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define mod 999911659
#define Mod 999911658
#define MN 35620
ll N,G,mo,X[4],fac[MN],inv[MN];
const int p[4]={2,3,4679,35617};
ll C(ll n,ll m)
{
if(n<m) return 0ll;
if(n<mo&&m<mo) return fac[n]*inv[m]%mo*inv[n-m]%mo;
return C(n%mo,m%mo)*C(n/mo,m/mo)%mo;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b) return (void)(d=a,x=1,y=0);
exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
ll CRT()
{
ll ret=0,d,x,y;register int i;
for(i=0;i<4;++i)
{
exgcd(Mod/p[i],p[i],d,x,y);
ll INV=(x%Mod+Mod)%Mod;
(ret+=INV*X[i]%Mod*(Mod/p[i])%Mod)%=Mod;
}
return ret;
}
ll fpow(ll x,ll m)
{
ll ret=1;
for(;m;x=x*x%mod,m>>=1) if(m&1) ret=ret*x%mod;
return ret;
}
int main()
{
N=read();G=read();
register int i,T;
for(T=0;T<4;++T)
{
mo=p[T];fac[0]=1;
for(i=1;i<mo;++i) fac[i]=fac[i-1]*i%mo;
inv[mo-1]=mo-1;
for(i=mo-2;~i;--i) inv[i]=inv[i+1]*(i+1)%mo;
for(i=1;i*i<=N;++i)
{
if(N%i) continue;
(X[T]+=C(N,i))%=mo;
if(N/i-i) (X[T]+=C(N,N/i))%=mo;
}
}
printf("%lld
",fpow(G,CRT()));
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!