[bzoj 1951] [Sdoi2010]古代猪文

传送门

Description

给定两个数\(N\)\(G\) (\(N,G\leq 10^9\)),求

\[ans=G^{\sum_{d|N} \tbinom{N}{d}} (mod \ 999911659) \]

Solution

  1. 运用欧拉定理,所以指数只需要$\sum_{d|N}\tbinom{N}{d} mod \ 999911658 $
  2. 运用\(Lucas\)定理,\(\tbinom{m}{n} \equiv \tbinom{m/p}{n/p} \tbinom{m\%p}{n\%p}\ \mod p\),其中\(p\)是个质数
  3. 但是\(999911658\)并不是个质数,不能用\(Lucas\)定理。这时我们把它分解:\(999911658=2*3*4679*35617\),对这\(4\)个质因子分别求解出它的答案\(X[i]\),原问题转化成一个解线性方程组的问题,因为\(999911658\)比较小,所以直接用中国剩余定理即可解决。

\[G的指数=\sum X[i] \ \left ( \frac{M}{p_i}\right )^{-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\n",fpow(G,CRT()));
	return 0;
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-01-09 16:49  PaperCloud  阅读(134)  评论(0编辑  收藏  举报