one

 

7月5日

  1. 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
 
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 705;
const int MAXA = 10005;
int a[MAXN],b[MAXN],dp[MAXA];
int n;
int gcd(int m,int n)
{
        if (m<n) {
               int t = m;m = n; n = t;
        }
        if (m % n==0) return n;
        else return gcd(n,m%n);
}
int main()
{
        
        scanf("%d",&n);
        for (int i = 1; i<=n; i++)
        scanf("%d",&b[i]);
    sort(b+1,b+n+1);
    int count = 0,now = b[1];
    a[++count] = now;
    int ans = 0;
        for (int i = 2;i<=n;i++)
        {
     if (b[i]!= now) {
                       now = b[i];
                       a[++count] = now;
     }
     else ans ++;
    }
     int max = a[1];
     memset(dp, 0x3f3f,sizeof(dp));
     for (int i = 1;i<=count;i++)
     {
        dp[a[i]] = 1;
        if (a[i]>max)  max = a[i];
         }
         for (int i = 1;i<=count;i++)
          for (int j = 1;j<=max;j++)
           {
                       int cur = gcd(a[i],j);
                       if (dp[cur]>dp[j]+1) dp[cur] = dp[j] + 1;
           }
        int g = a[1];
        for (int i =2;i<=count;i++)
          g = gcd(g,a[i]);
        printf("%d",count-dp[g]+ans);
        return 0;
}

错因:

1.正解:DP: dp[i]表示使得最大公约数是i最小使用多少数。

             对于每个i枚举所有数,进行更新。

理由:1.gcd满足“交换律结合律”。

      2. 更新结果与搜索顺序无关。

做:审题:误把gcd当成了最大公因数。

改:no problem

得:缜密审题  动态思维

2.未完待续

3.未完待续

posted @ 2014-07-10 23:38  rubylan  阅读(192)  评论(0编辑  收藏  举报