前缀和+后缀和题目2 Coprime Sequence
-
题目分析:
输入一个整数n,代表测试集合,而每个测试集合,又需要先输入一个数字m,代表将输入数字的数目,每一个测试案例都构成了一个序列。
题目所问是在每个序列中,任意删除一个,那么求所得序列的最大约数。问什么时候可以让修改后的序列最大公约数最大。
我们知道GCD(a,b,c) = GCD(GCD(a,b),c) = GCD(a,GCD(b,c))
GCD是最大公约数的意思
我们可以知道这个定理很显然,但是具体证明需要用到数论里的知识,在这里就先不叙述,有兴趣的伙伴可以观看数论方面书籍。 -
算法设计:
我们可以设置一个前缀,即保留前n个数的最大公约数pre[],从n开始后面的最大公约数tail[]。
我们还需要辗转相除递归求公约数。 -
知识点
1.快速求公约数,辗转相除,或更相减损。
2.前缀和,后缀和。 -
代码
#include <stdio.h>
int temp[100000];
int pre[100000];
int tail[100000];
int getGCD(int a,int b)
{
if(a>b)
{
int temp = a;
a = b;
b = temp;
}
if(b%a==0)
return a;
else
return getGCD(a,b%a);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int k =1;k<=n;k++)
{
scanf("%d",&temp[k]);
}
pre[1] = temp[1];
tail[n] = temp[n];
for(int k = 2;k<=n;k++)
{
pre[k] = getGCD(pre[k-1],temp[k]);
}
for(int k=n-1;k>0;k--)
{
tail[k] = getGCD(tail[k+1],temp[k]);
}
int max = tail[2];
if(pre[n-1]>max)
max = pre[n-1];
for(int i =2;i<n;i++)
{
if(getGCD(pre[i-1],tail[i+1])>max)
max = getGCD(pre[i-1],tail[i+1]);
}
printf("%d\n",max);
}return 0;
}
over