BZOJ 1951SDOI2010 古代猪文

真是到很强的数学题

先利用欧拉定理A^B %p=A^(B%φ(p)+φ(p) ) %p

然后利用卢卡斯定理求出在modφ(p)的几个约数下的解

再利用中国剩余定理合并

计算答案即可

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=999911659;
 5 ll pri[5]={2,3,4679,35617};
 6 ll fac[5][35618],inv[5][35618],ans[5],n,g;
 7 void init(ll p,ll fac[],ll inv[])
 8 {
 9     fac[0]=1;
10     for(int i=1;i<=p;++i)fac[i]=fac[i-1]*i%p;
11     inv[1]=inv[0]=1;
12     for(int i=2;i<=p;++i)inv[i]=(p/i+1)*inv[i-p%i]%p;
13     for(int i=2;i<=p;++i)inv[i]=inv[i]*inv[i-1]%p;
14 }
15 ll C(ll a,ll b,ll p,ll fac[],ll inv[])
16 {
17     if(a<b)return 0;
18     if(a<p&&b<p)return fac[a]*inv[b]%p*inv[a-b]%p;
19     return C(a/p,b/p,p,fac,inv)*C(a%p,b%p,p,fac,inv)%p;
20 }
21 void exgcd(ll a,ll b,ll &x,ll &y)
22 {
23     if(!b){
24         x=1;y=0;return;
25     }
26     exgcd(b,a%b,x,y);
27     ll t=x;x=y;y=t-a/b*y;
28 }
29 ll CRT()
30 {
31     ll sum=0;
32     for(int i=0;i<4;++i)
33     {
34         ll x,y;
35         exgcd((mod-1)/pri[i],pri[i],x,y);
36         sum+=ans[i]*((mod-1)/pri[i])%(mod-1)*x%(mod-1);
37         sum%=(mod-1);
38     }
39     return sum;
40 }
41 void cal(ll x)
42 {
43     for(int i=0;i<4;++i)
44     {
45         ans[i]+=C(n,x,pri[i],fac[i],inv[i]);
46         ans[i]%=pri[i];
47     }
48     return;
49 }
50 
51 ll qmod(ll a,ll b)
52 {
53     ll ans=1;
54     while(b)
55     {
56         if(b&1)ans=ans*a%mod;
57         a=a*a%mod;b>>=1;
58     }
59     return ans;
60 }
61 int main()
62 {
63     for(int i=0;i<4;++i)init(pri[i],fac[i],inv[i]);
64     scanf("%d%d",&n,&g);
65     for(int i=1;i*i<=n;++i)
66     {
67         if(i*i==n)cal(i);
68         else if(n%i==0)cal(i),cal(n/i);
69     }
70     
71     ll ans=CRT();
72     ans=qmod(g%mod,ans+mod-1);
73     printf("%lld\n",ans);
74     return 0;
75 }

 

posted @ 2018-02-05 11:35  大奕哥&VANE  阅读(145)  评论(0编辑  收藏  举报