3 3 1 1 1 5 2 2 2 3 2 4 1 2 4 8Sample Output
1 2 2
题意:删除数列中的一个数,使得其他的数的最大公约数最大.
思路:首先要清楚一个数列的最大公约数是怎么求的:两个数求出gcd之后,在用这个gcd与另一个数求新的gcd,在用新的gcd与其他的数求一个新新的gcd........如此反复,知道弄完整个数列,最后得到的就是整个数列的gcd.
所以你可以知道求一个数列的gcd没有顺序之说,随便选那个数开始都可以。
这样我们就很好处理了:
设所求数列为a;
qian[i] 是a[i] 前面所有数字的gcd;
hou[i] 是a[i] 后面所有数字的gcd.
删除a[i]之后,新的数列的gcd就是gcd(qian[i-1], hou[i+1]);所以我们只需要遍历一下就可以求出最大的了.
上代码:
#include
#include
#include
#include
using namespace std;
int gcd(int x,int y)
{
return y==0 ? x : gcd(y,x%y);
}
int qian[100001];
int hou[100001];
int a[100001];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
qian[0] = 0;
hou[0] = 0;
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
qian[1] = a[1];
qian[2] = gcd(a[1],a[2]);
for(int i=3; i<=n; i++)
{
qian[i] = gcd(qian[i-1],a[i]);
}
hou[n] = a[n];
hou[n-1] = gcd(a[n-1],a[n]);
for(int i=n-2; i>=1; i--)
{
hou[i] = gcd(a[i],hou[i+1]);
}
int maxn = max(hou[2],qian[n-1]);
for(int i=2; i<=n-1; i++)
{
maxn = max(maxn, gcd(qian[i-1], hou[i+1]));
}
printf("%d\n",maxn);
}
return 0;
}