BZOJ4818 序列计数
4818: [Sdoi2017]序列计数
Time Limit: 30 Sec Memory Limit: 128 MBDescription
Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数。Alice还希望
,这n个数中,至少有一个数是质数。Alice想知道,有多少个序列满足她的要求。
Input
一行三个数,n,m,p。
1<=n<=10^9,1<=m<=2×10^7,1<=p<=100
Output
一行一个数,满足Alice的要求的序列数量,答案对20170408取模。
Sample Input
3 5 3
Sample Output
33
月考后日常颓水题,好久没有1A了,可能SDOI比较良心
SBDP,D[i]表示和为i的方案数,用所有的减去没有素数的,写出方程发现可以矩阵转移,然后乱敲
1 #include<bits/stdc++.h> 2 using namespace std; 3 template <class _T> inline void read(_T &_x) { 4 int _t; bool flag = false; 5 while ((_t = getchar()) != '-' && (_t < '0' || _t > '9')) ; 6 if (_t == '-') _t = getchar(), flag = true; _x = _t - '0'; 7 while ((_t = getchar()) >= '0' && _t <= '9') _x = _x * 10 + _t - '0'; 8 if (flag) _x = -_x; 9 } 10 using namespace std; 11 typedef long long LL; 12 const int mod = 20170408; 13 const int maxv = 200; 14 struct Mat { 15 int n, m, a[maxv][maxv]; 16 Mat() {} 17 Mat(int x, int y):n(x), m(y) { 18 for (register int i = 0, j; i < n; ++i) 19 for (j = 0; j < m; ++j) 20 a[i][j] = 0; 21 } 22 inline void init() {for (int i = 0; i < n; ++i) a[i][i] = 1; } 23 inline Mat operator * (Mat B) { 24 Mat C(n, B.m); 25 for (register int i = 0, j, k; i < n; ++i) 26 for (j = 0; j < B.m; ++j) 27 for (k = 0; k < m; ++k) { 28 C.a[i][j] += (int)((LL)a[i][k] * B.a[k][j] % mod); 29 if (C.a[i][j] >= mod) C.a[i][j] -= mod; 30 } 31 return C; 32 } 33 inline Mat operator ^ (int t) { 34 Mat res(n, m), tmp = *this; res.init(); 35 while (t) { 36 if (t & 1) res = res * tmp; 37 tmp = tmp * tmp, t >>= 1; 38 } 39 return res; 40 } 41 }; 42 const int maxp = 210; 43 const int maxm = 20000010; 44 int n, m, p; 45 int cnt_p[maxp], cnt_n[maxp]; 46 bool vis[maxm]; 47 int prime[maxm / 10], pcnt; 48 inline void Init() { 49 cnt_p[1 % p] = 1; 50 for (register int i = 2, j; i <= m; ++i) { 51 if (!vis[i]) { 52 prime[++pcnt] = i; 53 } else { 54 ++cnt_p[i % p]; 55 } 56 for (j = 1; j <= pcnt && i * prime[j] <= m; ++j) { 57 vis[i * prime[j]] = true; 58 if (i % prime[j] == 0) break; 59 } 60 } 61 int tmpa = m / p, tmpb = m % p; 62 for (register int i = 0; i < p; ++i) { 63 cnt_n[i] = tmpa; 64 cnt_n[i] += (i && i <= tmpb); 65 } 66 } 67 inline int getres(Mat &a) { 68 Mat x(p, 1); 69 x.a[0][0] = 1; 70 return ((a ^ n) * x).a[0][0]; 71 } 72 int main() { 73 //freopen(); 74 //freopen(); 75 read(n), read(m), read(p); 76 Init(); 77 Mat a(p, p), b(p, p); 78 for (int i = 0, j, to; i < p; ++i) { 79 for (j = 0; j < p; ++j) { 80 to = i + j; 81 if (to >= p) to -= p; 82 a.a[i][to] = cnt_n[j]; 83 b.a[i][to] = cnt_p[j]; 84 } 85 } 86 int ans = getres(a) - getres(b); 87 if (ans < 0) ans += mod; 88 cout << ans << endl; 89 return 0; 90 }
作者:HPL 出处:https://www.cnblogs.com/akhpl/ 感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文由CC BY-NC-ND 2.5授权,欢迎读者转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,谢谢。