D - 稳住GCD DP

http://acm.uestc.edu.cn/#/problem/show/923

给定一堆数字,求其所有数字的gcd。

现在要删除最多的数字,使得剩下的数字的gcd和原来的一样。

设dp[i][val]表示在前i个数中,得到val这个数字所需的最小数字,怎么得到val这个数字?就是gcd得到。

dp[i][gcd]

然后转移就是

dp[i][a[i]] = 1是必然的,自己一个

枚举新数字得到新的gcd  val

dp[i][val] = min(dp[i][val], dp[i - 1][j]  + 1)

每次都要和自己比较一下,因为防止自己更小,就是dp[i][val]本来就是1,这样就不需要枚举其他数加入来了,。

//#include<stdio.h>
//int main() {
//    int i;
//    char a[10][3]= {"一","和","三","四","物","社","嗯","阶","己","嗯"};
//    for(i=0; i<10; i++)
//        printf("%s\n",a[i]);
//    return 0;
//}

#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 dp[700 + 20][10000 + 20];
int a[10000 + 20];
void work() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    int ans = a[1];
    for (int i = 2; i <= n; ++i) {
        ans = __gcd(ans, a[i]);
    }
    memset(dp, 0x3f, sizeof dp);
    dp[1][a[1]] = 1;
    for (int i = 2; i <= n; ++i) {
        dp[i][a[i]] = 1; //自己一直出现,一次就够
        for (int j = 1; j <= 10000; ++j) {
            if (dp[i - 1][j] != inf) {
                dp[i][j] = min(dp[i][j], dp[i - 1][j]);
                int t = __gcd(j, a[i]);
                dp[i][t] = min(dp[i][t], dp[i - 1][j] + 1);
            }
        }
    }
    cout << n - dp[n][ans] << endl;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work();
    return 0;
}

时间: 2024-10-07 07:08:30

D - 稳住GCD DP的相关文章

UESTC 923 稳住GCD DP + GCD

定义:dp[i][j] 表示 在前i个数中,使整个gcd值为j时最少取的数个数. 则有方程: gg = gcd(a[i],j) gg == j : 添加这个数gcd不变,不添加,  dp[i][j] = dp[i-1][j] gg != j: t添加,更新答案,                dp[i][gg] = dp[i-1][j] + 1 最后答案为dp[n][g] (g为原始的所有数的gcd) 时间复杂度: O(n*max(a[i])) 代码: #include <iostream>

hdu-5656 CA Loves GCD(dp+数论)

题目链接: CA Loves GCD Time Limit: 6000/3000 MS (Java/Others)     Memory Limit: 262144/262144 K (Java/Others) Problem Description CA is a fine comrade who loves the party and people; inevitably she loves GCD (greatest common divisor) too. Now, there are 

uestc 稳住GCD

DP 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<map> 9 #include<iomanip> 10 #include<climits&

hdu CA Loves GCD(dp)

一道我想骂人的题,差点把我气炸了. 题意: 求一个数的集合中(非多重集,每个数只出现一次)所有子集的gcd的和.结果MOD10^8+7输出. 输入输出不说了,自己看吧,不想写了. 当时我真把它当作数论题来写了,以为可以推导出什么公式然后化简大量重复的操作的.结果最后也没找到.最后题解说是dp,我同学说是暴力,吐血10升. 然后弄出来dp方程之后还是反复的wa,方程明明没啥问题,愣是卡了2个小时找不出错误,心情烦躁的要命,坑爹的室友还各种看视频打游戏,还不带耳机,我自己只好带着耳机大声放音乐,最后

hdu 5656 CA Loves GCD dp

CA Loves GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Problem Description CA is a fine comrade who loves the party and people; inevitably she loves GCD (greatest common divisor) too. Now, there are N diffe

GCD(st表)

GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3432    Accepted Submission(s): 1227 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There a

HDU 5726 GCD (RMQ + 二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726 给你n个数,q个询问,每个询问问你有多少对l r的gcd(a[l] , ... , a[r]) 等于的gcd(a[l'] ,..., a[r']). 先用RMQ预处理gcd,dp[i][j] 表示从i开始2^j个数的gcd. 然后用map存取某个gcd所对应的l r的数量. 我们可以在询问前进行预处理,先枚举i,以i为左端点的gcd(a[i],..., a[r])的种类数不会超过log2(n)

hdu 5869 区间不同GCD个数(树状数组)

Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 221    Accepted Submission(s): 58 Problem Description This is a simple problem. The teacher gives Bob a list of probl

HDU 5726 GCD 区间GCD=k的个数

GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2742    Accepted Submission(s): 980 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There ar