zoj3662 dp 离散优化
2016-05-14 20:36
337 查看
Problem:
让你求满足,和为n,且最小公倍数为m,的k个数的种数.
Analy:
首先很容想到dp[i][j][k]:前i个数,最小公倍数为j,和为k的状态定义.
转移的时候,就遍历第i个数后面加一个d(0<=d<=n),有转移方程:
dp[i+1][lcm(d,j)][k+d]+=dp[i][j][k]
但是这里维度肯定多了.
观察到lcm有一个性质,那就是n个数的lcm要为m,那么这n个数必须是m的约数,然后我们打表观察到
1000以内的数的约数最多有32个,就可以把第二维j离散化为只有32大小.
还有一个优化就是求lcm会多一个log的常数,我们需要打好所有约数相互lcm的表即可.
让你求满足,和为n,且最小公倍数为m,的k个数的种数.
Analy:
首先很容想到dp[i][j][k]:前i个数,最小公倍数为j,和为k的状态定义.
转移的时候,就遍历第i个数后面加一个d(0<=d<=n),有转移方程:
dp[i+1][lcm(d,j)][k+d]+=dp[i][j][k]
但是这里维度肯定多了.
观察到lcm有一个性质,那就是n个数的lcm要为m,那么这n个数必须是m的约数,然后我们打表观察到
1000以内的数的约数最多有32个,就可以把第二维j离散化为只有32大小.
还有一个优化就是求lcm会多一个log的常数,我们需要打好所有约数相互lcm的表即可.
/*** ***/ #include <iostream> #include <cstring> using namespace std; typedef long long ll; const int mod = 1e9 + 7; ll dp[2][33][1111]; int d[33], cnt, lcms[33][33]; int gcd(int a, int b) { if (!b) return a; return gcd(b, a % b); } int lcm(int x, int y) { return x * y / gcd(x, y); } void pre(int x) { cnt = 0; for (int i = 1; i <= x; i++) { if (x % i == 0) d[cnt++] = i; } for (int i = 0; i < cnt; i++) { for (int j = 0; j < cnt; j++) { lcms[i][j] = lcm(d[i], d[j]); } } } int getid(int x) { return lower_bound(d, d + cnt, x) - d; } int main(void) { int n, m, K; while (cin >> n >> m >> K) { pre(m); memset(dp, 0, sizeof(dp)); dp[0][0][0] = 1; for (int i = 0; i < K; i++) { for (int j = 0; j < cnt; j++) { for (int k = 0; k <= n; k++) { if (dp[i % 2][j][k]) for (int l = 0; l < cnt; l++) { if (k + d[l] <= n) { dp[(i + 1) % 2][ getid(lcms[l][j]) ][k + d[l]] += dp[i % 2][j][k] % mod; } } dp[i % 2][j][k] = 0; } } } cout << dp[K % 2][cnt - 1] % mod << endl; } }
相关文章推荐
- 1096. Consecutive Factors (20)——PAT (Advanced Level) Practise
- poj 1836
- JS 将字符串转换成日期类型
- 面向对象的登录系统(QQ登录窗体)
- C++_(矩阵)快速幂
- swift 利用 Reflect(字典转模型)
- httpClient Post 加号会被转换为空格
- 【数据库】where 1=1 和 where 1=0
- HDU 2553 N皇后问题 (DFS)
- 第10、11周程序阅读 继承和派生 1
- 零售行业常见数据分析简介
- SSIS 学习之旅 第一个SSIS 示例(二)
- Android ActionBarSherlock使用教程
- ST表学习
- Apache Flink源码解析之stream-transformation
- Linux 文件系统剖析
- 1095. Cars on Campus (30)——PAT (Advanced Level) Practise
- 机器学习基础(六十三)—— 奇异值分解(SVD)
- Modular Multiplicative Inverse(模乘逆元)
- 我在北京的日子系列之一