BZOJ4818 [SDOI2017] 序列计数 【矩阵快速幂】

题目分析:

一个很显然的同类项合并。注意到p的大小最大为100,考虑把模p意义下相同的求出来最后所有的减去没有质数的做矩阵快速幂即可。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 20000005;
 5 
 6 const int mod = 20170408;
 7 
 8 int n,m,q;
 9 
10 int base[105][2];
11 
12 int flag[maxn],prime[maxn/10],num;
13 
14 int mat[105][105],Res[105][105],po[105][105];
15 
16 void init(){
17     flag[1] = 1;
18     for(int i=2;i<=m;i++){
19     if(!flag[i]) prime[++num] = i;
20     for(int j=1;j<=num&&i*prime[j]<=m;j++){
21         flag[i*prime[j]] = 1;
22         if(i%prime[j] == 0) break;
23     }
24     }
25     for(int i=1;i<=m;i++){
26     if(flag[i]) base[i%q][1]++;
27     base[i%q][0]++;
28     }
29 }
30 
31 void BuildMatrix(int now){
32     memset(mat,0,sizeof(mat));
33     for(int i=0;i<q;i++){
34     for(int j=0;j<q;j++){
35         int nw = j-i;if(nw < 0) nw += q;
36         mat[j][nw] += base[i][now];
37     }
38     }
39 }
40 
41 void fast_pow(int now){
42     if(now == 1){
43     for(int i=0;i<q;i++) for(int j=0;j<q;j++) Res[i][j]=mat[i][j];
44     }else{
45     fast_pow(now/2);
46     memset(po,0,sizeof(po));
47     for(int k=0;k<q;k++)
48         for(int i=0;i<q;i++)
49         for(int j=0;j<q;j++){
50             po[i][j] += (1ll*Res[i][k]*Res[k][j])%mod;
51             po[i][j] %= mod;
52         }
53     for(int i=0;i<q;i++)for(int j=0;j<q;j++)Res[i][j]=po[i][j];
54     if(now & 1){
55         memset(po,0,sizeof(po));
56         for(int k=0;k<q;k++)
57         for(int i=0;i<q;i++)
58             for(int j=0;j<q;j++){
59             po[i][j] += (1ll*Res[i][k]*mat[k][j])%mod;
60             po[i][j] %= mod;
61             }
62         for(int i=0;i<q;i++)for(int j=0;j<q;j++)Res[i][j]=po[i][j];
63     }
64     }
65 }
66 
67 void work(){
68     BuildMatrix(0);
69     fast_pow(n);
70     int ans = Res[0][0];
71     BuildMatrix(1);
72     fast_pow(n);
73     ans -= Res[0][0]; 
74     if(ans < 0) ans += mod;
75     printf("%d",ans);
76 }
77 
78 int main(){
79     scanf("%d%d%d",&n,&m,&q);
80     init();
81     work();
82     return 0;
83 }

 

posted @ 2018-05-27 20:32  menhera  阅读(170)  评论(0编辑  收藏  举报