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 }