1. 程式人生 > >BZOJ1951: [Sdoi2010]古代豬文

BZOJ1951: [Sdoi2010]古代豬文

又是一個被卡了很久的題。。
差點就對指數取模了QAQ,然後突然發現有問題。。就傻掉了這該怎麼做。

ans=Gd|nCdnmodP
根據費馬小定理(G,P),一個數GP1次方在模P意義下為1.
ans=Gd|nCdnmod(P1)modP
P1=23467935617
那麼對於每一個質數分別處理然後CRT合併就行了
求大組合數就直接上Lucas定理。
其實化簡成第二個式子感覺上就不那麼難做了。。
然而死於 999911657999911659

【程式碼】

#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; }