20140705 testC DP

testC

输入文件: testC.in  输出文件testC.out 时限1000ms

问题描述:

给你一组数,a1,a2,a3,⋯,an

令:G=gcd(a1,a2,a3,⋯,an)

现在从中任意删除一些数字,设剩下的数为:al1,al2,al3,⋯,alm

再令:g=gcd(al1,al2,al3,⋯,alm)

现要求G=g,问最多能删除多少数?

输入描述:

第一行一个数n,第二行n个数a1,a2,a3,⋯,an

1≤n≤700

1≤ai≤10000

输出描述:

输出只有一个数,表示最多能删除多少数。

样例输入:

3
4 6 8

样例输出:

1


考试的时候觉得似乎答案只有n-1 n-2 0 三种情况
后来仔细想想发现不是这样 >_<
正解是dp
dp[i]表示最大公倍数为i最少需要多少数
转移方程
dp[gcd(i,a[k])] = min(dp[gcd(i,a[k])],dp[i]+1)
答案便是 n-dp[G]

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define MAX_num 10010
 5 #define INF 0x3f3f3f
 6 
 7 int gcd(int a,int b) {
 8     if (a%b==0) return b;
 9     return gcd(b,a%b);
10 }
11 
12 int min(int a,int b) {
13     return a<b?a:b;
14 }
15 
16 int n;
17 int dp[MAX_num];
18 
19 int main() {
20     scanf("%d",&n);
21     memset(dp,INF,sizeof(dp));
22     int x;
23     scanf("%d",&x);
24     int G=x;
25     dp[x]=1;
26     for (int i=2;i<=n;i++) {
27         scanf("%d",&x);
28         dp[x]=1;
29         G=gcd(G,x);
30         for (int j=1;j<MAX_num;j++) {
31             int g=gcd(j,x);
32             dp[g]=min(dp[g],dp[j]+1);
33         }
34     }
35     printf("%d",n-dp[G]);
36 }
View Code
原文地址:https://www.cnblogs.com/fjmmm/p/3828482.html