AcWing 213. 古代猪文

原题链接

考察:欧拉降幂+中国剩余定理+lucas求组合数

思路: 

      本道题的答案求出幂后快速幂一下即可,所以主要是求幂,由欧拉降幂可知,我们的幂是需要%phi[mod]的.但mod=999911659,是一个质数,mod-1后是一个合数.设此合数为M,我们需要找的就是组合数和%M.但本题直接求组合数会超时,因此考虑lucas求组合数.但lucas需要模数为质数.

      这里就涉及到同余的除法定理二, 假设m是n的倍数, (a-b)%m==(a-b)%n,根据这条性质我们可以将M分解质因数.可以发现质因数的最小公倍数刚好==M,分别求出质因数的余数,联立即可求答案.

坑点:

       当q = mod时,我们需要特判,否则输出1.

找bug找好久,结果发现是模数写错了....

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 using namespace std;
 5 typedef long long ll;
 6 const int mod = 999911659,N = 36000,M = 1600;
 7 vector<int> v,d;
 8 ll fact[4][N],infact[4][N],divs[M];
 9 int n,q;
10 ll qsm(ll a,ll k,ll q)
11 {
12     ll res = 1;
13     while(k) 
14     {
15         if(k&1) res = res*a%q;
16         a = a*a%q;
17         k>>=1; 
18     }
19     return res;
20 }
21 void inits(int q,int id)
22 {
23     infact[id][0] = fact[id][0] = 1;
24     for(int i=1;i<=q;i++)
25     {
26         fact[id][i] = fact[id][i-1]*i%q;
27         infact[id][i] = infact[id][i-1]*qsm(i,q-2,q)%q;
28     }
29 }
30 ll C(ll a,ll b,int id)
31 {
32     if(a<b) return 0;
33     ll res = fact[id][a]*infact[id][b]%v[id]*infact[id][a-b]%v[id];
34     return res;
35 }
36 ll lucas(ll a,ll b,int id)
37 {
38     if(a<v[id]&&b<v[id]) return C(a,b,id);
39     return C(a%v[id],b%v[id],id)*lucas(a/v[id],b/v[id],id)%v[id];
40 }
41 void GetDiv(int n)
42 {
43     for(int i=1;i<=n/i;i++)
44         if(n%i==0)
45         {
46             d.push_back(i);
47             if(i!=n/i) d.push_back(n/i);
48         }
49 }
50 int main()
51 {
52     scanf("%d%d",&n,&q);
53     if(q==N) { printf("0\n"); return 0; } 
54     ll ans = 0;
55     v.push_back(2); v.push_back(3); v.push_back(4679);
56     v.push_back(35617);
57     for(int i=0;i<v.size();i++) inits(v[i],i);
58     GetDiv(n);
59     for(int i=0;i<v.size();i++)
60         for(int j=0;j<d.size();j++)
61             divs[i]= (divs[i]+lucas(n,d[j],i))%v[i];
62     ll M = mod-1;
63     for(int i=0;i<v.size();i++)
64     {
65         ll tmp = mod/v[i];
66         ll rtmp = qsm(tmp,v[i]-2,v[i]);
67         ans = (ans+divs[i]*tmp%M*rtmp%M)%M;
68     }
69     printf("%lld\n",qsm(q,ans,mod));
70     return 0;
71 }

 

posted @ 2021-01-30 16:03  acmloser  阅读(66)  评论(0编辑  收藏  举报