您的位置:首页 > 其它

BZOJ1951: [Sdoi2010]古代猪文

2017-06-01 08:51 288 查看
BZOJ1951

又是一个被卡了很久的题。。

差点就对指数取模了QAQ,然后突然发现有问题。。就傻掉了这该怎么做。

ans=G∑d|nCdnmodP

根据费马小定理(G,P)互质,一个数G的P−1次方在模P意义下为1.

那么ans=G∑d|nCdnmod (P−1)mod P

P−1=2∗3∗4679∗35617

那么对于每一个质数分别处理然后CRT合并就行了

求大组合数就直接上Lucas定理。

其实化简成第二个式子感觉上就不那么难做了。。

然而死于 999911657 999911659

【代码】

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 100005
#define Mod 999911659
#define INF 0x7fffffff
using namespace std;
typedef long long ll;

ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}

ll ans;
int n,G,cnt;
ll p[]={0,2,3,4679,35617},Fac[35618];

ll Qpow(ll x,ll y,ll mod){
if(x==mod) return 0;
ll rtn=1;
while(y) {
if(y&1) rtn=rtn*x%mod;
x=x*x%mod;y>>=1;
}
return rtn;
}

ll C(ll x,ll y,ll mod) {
return Fac[x]*Qpow(Fac[y],mod-2,mod)%mod*Qpow(Fac[x-y],mod-2,mod)%mod;
}

ll Lucas(ll x,ll y,ll mod){
if(x<y) return 0;
if(x<mod&&y<mod) return C(x,y,mod);
return Lucas(x/mod,y/mod,mod)*Lucas(x%mod,y%mod,mod)%mod;
}

ll Solve(int mod)
{
Fac[0]=1;
for(int i=1;i<mod;i++) Fac[i]=Fac[i-1]*i%mod;
ll t1=(n+1)%mod;
for(int i=2;i*i<=n;i++) if(n%i==0)
{
t1=(t1+Lucas(n,i,mod))%mod;
if(i*i!=n)
t1=(t1+Lucas(n,n/i,mod))%mod;
}
return t1;
}

void Exgcd(ll a,ll b,ll &x,ll &y){
if(b){
Exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else x=1,y=0;
}

ll Inv(ll a,ll b){
ll x,y;
Exgcd(a,b,x,y);
return (x%b+b)%b;
}

int main()
{
n=read(),G=read();ll MOD=Mod-1;
for(int i=1;i<=4;i++)
{
ll Mi=MOD/p[i];
ll t1=Solve(p[i]),t2=Inv(Mi,p[i]);
ans=(ans+t1*t2%MOD*Mi%MOD)%MOD;
}
printf("%lld\n",Qpow(G,ans,Mod));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: