7月5日
- 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.未完待续