HDU 5902 GCD is Funny DP
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5902 GCD is Funny DP相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?pid=5902
一眼看上去,以为是枚举两个数,然后去重gcd即可。
但是不是
6 6 10 15这样的数据
应该是1 2 3 5 6
1是从6 6 15得到gcd = 3,然后3和10搭配得到的。
那么就是其它的gcd能够作为新的数字,去枚举其他数字,得到其他gcd。其实这个应该很容易想到的,但是比赛的时候却认为只用枚举两个就够了,可能是因为1001,觉得应该是水题吧。其实是自己蔡。。
那么考虑dp。
dp[i][val]表示在前i个数中,能否得到val这个值。
这是一个类似背包的问题了
先预处理出任意两个的所得到的gcd值。
然后枚举每个a[i]来加入前i - 1个数,对于出现过的,dp[i][j]也能出现,一直传递上去即可。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> int n; const int maxn = 1000 + 20; int a[maxn]; int gcd(int n, int m) { if (n % m == 0) { return m; } else return gcd(m, n%m); } bool dp[maxn][maxn]; //int index; void work() { // ++index; memset(dp, 0, sizeof dp); int mx = -inf; scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); mx = max(mx, a[i]); } for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { dp[i][gcd(a[i], a[j])] = 1; } } for (int i = 3; i <= n; ++i) { for (int j = 1; j <= mx; ++j) { if (dp[i - 1][j]) { dp[i][j] = 1; dp[i][gcd(j, a[i])] = 1; } } } bool flag = false; for (int i = 1; i <= mx; ++i) { if (dp[n][i]) { if (flag) { printf(" %d", i); } else { printf("%d", i); flag = true; } } } printf("\\n"); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; scanf("%d", &t); while(t--) { work(); } return 0; }
不memset好像更快
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> int n; const int maxn = 1000 + 20; int a[maxn]; int gcd(int n, int m) { if (n % m == 0) { return m; } else return gcd(m, n%m); } int dp[maxn][maxn]; int index; void work() { ++index; // memset(dp, 0, sizeof dp); int mx = -inf; scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); mx = max(mx, a[i]); } for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { dp[i][gcd(a[i], a[j])] = index; } } for (int i = 3; i <= n; ++i) { for (int j = 1; j <= mx; ++j) { if (dp[i - 1][j] == index) { dp[i][j] = index; dp[i][gcd(j, a[i])] = index; } } } bool flag = false; for (int i = 1; i <= mx; ++i) { if (dp[n][i] == index) { if (flag) { printf(" %d", i); } else { printf("%d", i); flag = true; } } } printf("\\n"); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; scanf("%d", &t); while(t--) { work(); } return 0; }
以上是关于HDU 5902 GCD is Funny DP的主要内容,如果未能解决你的问题,请参考以下文章