bzoj 4818 [Sdoi2017]序列计数(简单容斥+快速幂加速dp)
来源:互联网 发布:龙腾世纪2 知乎 编辑:程序博客网 时间:2024/06/09 17:23
题意:Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数。Alice还希望,这n个数中,至少有一个数是质数。Alice想知道,有多少个序列满足她的要求。1≤n≤1e9,1≤m≤2e7,1≤p≤100
思路:至少有一个质数转换成全部方案-无质数方案。然后dp[i][j]:序列长度为i且这i个数字的加和%p=j的方案数。写出转移矩阵,快速幂即可。
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int mod = 20170408;int n, m, p;const int maxn = 3e7 + 7;bool check[maxn];const int primeLimit = 1860000 + 5;int prime[primeLimit];int sieve(LL n){ memset(check, false, sizeof(check));//i为素数时, check[i]是false check[0] = check[1] = true; int tot = 0; for(LL i = 2; i <= n; i++) { if(!check[i]) prime[tot++] = i; for(LL j = 0; j < tot && i * prime[j] <= n; j++) { check[i * prime[j]] = true; if(i % prime[j] == 0) break; } } return tot;}const int mSize = 105;struct Matrix{ int v[mSize][mSize]; friend Matrix operator* (const Matrix& a, const Matrix& b) { Matrix c; memset(c.v, 0, sizeof(c.v)); for (int k = 0; k < mSize; k++) { for (int i = 0; i < mSize; i++) { if(a.v[i][k] == 0) continue; for (int j = 0; j < mSize; j++) { if(b.v[k][j] == 0) continue; c.v[i][j] = c.v[i][j] + 1LL * a.v[i][k] * b.v[k][j] % mod; c.v[i][j] %= (mod); } } } return c; } friend Matrix operator^ (Matrix x, LL n) { Matrix ans; for (int i = 0; i < mSize; i++) for (int j = 0; j < mSize; j++) ans.v[i][j] = (i == j); while (n) { if (n & 1) ans = ans * x; x = x * x; n >>= 1; } return ans; }};int b[200 + 5];int solve1(){ for(int i = 1; i <= m; i++) b[i % p] ++; Matrix a; memset(a.v, 0, sizeof(a.v)); for(int i = 1; i <= m; i++) { int num = (p - i % p) % p; a.v[0][num]++; } for(int i = 1; i < p; i++) { for(int j = 0; j < p; j++) { a.v[i][j] = a.v[i - 1][(j - 1 + p) % p]; } } a = a ^ (n-1); int ans = 0; for(int i = 0; i < p; i++) { ans = ans + 1LL * b[i] * a.v[0][i] % mod; ans %= mod; } return ans;}int solve2(){ memset(b, 0, sizeof(b)); for(int i = 1; i <= m; i++) { if(check[i]) b[i % p] ++; } Matrix a; memset(a.v,0,sizeof(a.v)); for(int i = 1; i <= m; i++) { if(check[i]) { int num = (p - i % p) % p; a.v[0][num]++; } } for(int i = 1; i < p; i++) { for(int j = 0; j < p; j++) { a.v[i][j] = a.v[i - 1][(j - 1 + p) % p]; } } a = a ^ (n-1); int ans = 0; for(int i = 0; i < p; i++) { ans = ans + 1LL * b[i] * a.v[0][i] % mod; ans %= mod; } return ans;}int main(){ scanf("%d%d%d", &n, &m, &p); sieve(m + 5); printf("%d\n", (solve1() - solve2() + mod) % mod); return 0;}
阅读全文
0 0
- bzoj 4818 [Sdoi2017]序列计数(简单容斥+快速幂加速dp)
- bzoj 4818: [Sdoi2017]序列计数(DP+矩阵快速幂)
- LOj #2002. 「SDOI2017」序列计数 (容斥+dp+矩阵快速幂)
- bzoj 4818 [Sdoi2017]序列计数 矩阵乘法优化dp+容斥
- [DP 倍增] BZOJ 4818 [Sdoi2017]序列计数
- [BZOJ4818][Sdoi2017][容斥原理][矩阵优化DP]序列计数
- [BZOJ4818][SDOI2017]序列计数(DP+容斥原理+矩乘)
- 【动态规划20】bzoj4818[sdoi2017]序列计数(dp+矩阵快速幂)
- BZOJ 4818: [Sdoi2017]序列计数 (动态规划+矩阵乘法)
- 4818: [Sdoi2017]序列计数
- bzoj 4818: [Sdoi2017]序列计数 动态规划+矩阵乘法
- bzoj4818【SDOI2017】序列计数 矩阵快速幂+动态规划
- bzoj4818 [Sdoi2017]序列计数(矩阵)
- BZOJ4818 [Sdoi2017]序列计数
- 【SDOI2017】序列计数
- BZOJ4818: [Sdoi2017]序列计数
- bzoj4818 [Sdoi2017]序列计数
- 【bzoj4818】[Sdoi2017]序列计数
- PV,VG,LV的关系和操作
- 2017.11.3测试
- 3秒切换
- MVP 替换标题栏,并在左右添加点击事件
- windows下尝试graphx的一个例子
- bzoj 4818 [Sdoi2017]序列计数(简单容斥+快速幂加速dp)
- 全面了解equals与==的区别
- Python的绝对路径和相对路径
- 【BZOJ1084】最大子矩阵(动态规划)
- 使用Scanner时的一个注意事项
- 将全志R16平台上的MIPI屏迁移到全志R40平台上(草稿)
- Python的Socket
- 拉格朗日乘子法、KKT条件、线性规划对偶理论
- JAVA内存分配分析/栈内存、堆内存