码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5902 GCD is Funny DP

时间:2016-09-24 23:20:10      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:

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;
}
View Code

 不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;
}
View Code

 

HDU 5902 GCD is Funny DP

标签:

原文地址:http://www.cnblogs.com/liuweimingcprogram/p/5904367.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!