题目
描述
Do you know what is called ``Coprime Sequence''? That is a sequence consists of n𝑛 positive integers, and the GCD (Greatest Common Divisor) of them is equal to 1.
你知道什么叫互质数列吗?也就是说,一个序列由 n𝑛 个正整数组成,它们的最大公因子(GCD)等于1。
``Coprime Sequence'' is easy to find because of its restriction. But we can try to maximize the GCD of these integers by removing exactly one integer. Now given a sequence, please maximize the GCD of its elements.
“互质序列”很容易找到,因为它的限制。但是我们可以通过删除一个整数来最大化这些整数的GCD。现在给出一个序列,请最大化其元素的GCD。
你知道什么叫互质数列吗?也就是说,一个序列由 n𝑛 个正整数组成,它们的最大公因子(GCD)等于1。
``Coprime Sequence'' is easy to find because of its restriction. But we can try to maximize the GCD of these integers by removing exactly one integer. Now given a sequence, please maximize the GCD of its elements.
“互质序列”很容易找到,因为它的限制。但是我们可以通过删除一个整数来最大化这些整数的GCD。现在给出一个序列,请最大化其元素的GCD。
Input 输入
The first line of the input contains an integer T(1≤T≤10)𝑇(1≤𝑇≤10), denoting the number of test cases.
输入的第一行包含一个整数 T(1≤T≤10)𝑇(1≤𝑇≤10) ,表示测试用例的数量。
In each test case, there is an integer n(3≤n≤100000)𝑛(3≤𝑛≤100000) in the first line, denoting the number of integers in the sequence.
在每个测试用例中,第一行有一个整数 n(3≤n≤100000)𝑛(3≤𝑛≤100000) ,表示序列中整数的数量。
Then the following line consists of n𝑛 integers a1,a2,...,an(1≤ai≤109)𝑎1,𝑎2,...,𝑎𝑛(1≤𝑎𝑖≤109), denoting the elements in the sequence.
然后下面的行由 n𝑛 整数 a1,a2,...,an(1≤ai≤109)𝑎1,𝑎2,...,𝑎𝑛(1≤𝑎𝑖≤109) 组成,表示序列中的元素。
输入的第一行包含一个整数 T(1≤T≤10)𝑇(1≤𝑇≤10) ,表示测试用例的数量。
In each test case, there is an integer n(3≤n≤100000)𝑛(3≤𝑛≤100000) in the first line, denoting the number of integers in the sequence.
在每个测试用例中,第一行有一个整数 n(3≤n≤100000)𝑛(3≤𝑛≤100000) ,表示序列中整数的数量。
Then the following line consists of n𝑛 integers a1,a2,...,an(1≤ai≤109)𝑎1,𝑎2,...,𝑎𝑛(1≤𝑎𝑖≤109), denoting the elements in the sequence.
然后下面的行由 n𝑛 整数 a1,a2,...,an(1≤ai≤109)𝑎1,𝑎2,...,𝑎𝑛(1≤𝑎𝑖≤109) 组成,表示序列中的元素。
Output 输出
For each test case, print a single line containing a single integer, denoting the maximum GCD.
对于每个测试用例,打印一行包含一个整数的行,表示最大GCD。
对于每个测试用例,打印一行包含一个整数的行,表示最大GCD。
Sample 样品
Input 输入copy 副本 | Output 输出copy 副本 |
---|---|
3
3
1 1 1
5
2 2 2 3 2
4
1 2 4 8
| 1
2
2 |
分析
该题意思是给出一个数组 求出这个数组的最大公约数后 选择删去数组里的一个数 再求这个数组的最大公约数 然后让我们输出删除一个元素后得到的最大公约数。
我是在输入时就先把每个元素出现的个数就统计一下 如果已经有两个相同元素了 那么这个元素就不再存到数组中(保证数据重复性不会太高 以免数据重复过多而造成时间复杂度爆掉), 然后等删除数据时只尝试删除只出现过一次的数据(因为如果这个数据出现过两次及以上了 在只删除一个元素的情况下也就显得没意义了还会徒增时间复杂度),然后多个数据会统计两次是因为防止出现第一个示例那种全是相同元素的情况;等把每个尝试删除的元素删除后 直接对g数组排序 最后得到的[nn]就是删除元素的最大公约数了 再跟gi比较 输出最大的即可。
坑点
数据很大 所以存储每个元素次数的时候要用map函数映射 有可能会出现删了数比没删数还小 所以要计算一次没删元素之前的最大公约数 最后 记得初始化数据!!
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const ll len=1e5+10;
int t,n,a[len],g1,g[len],b,nn;
void getgn(int x)//删除a数组中第i个数后得到的最大公约数
{
for(int i=1;i<=nn;i++)
{
if(i==x)
continue;
g[x]=__gcd(g[x],a[i]);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
map<int,int> num;
nn=0;
g1=1;
memset(a,0,sizeof(a));
memset(g,0,sizeof(g));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&b);
num[b]++;//用map映射存每个元素出现的次数
if(num[b]<3) a[++nn]=b;//如果这个数出现2次以上了就不存入a数组了 以达到降低时间复杂度的目的
}
g1=a[1];
for(int i=2;i<=n;i++)//求还没删元素前的最大公约数g1
g1=__gcd(g1,a[i]);
for(int i=1;i<=nn;i++)//遍历数组a
{
if(num[a[i]]==1)//如果这个元素只出现了一次 那去计算删除这个元素后得到的最大公约数
getgn(i);
}
sort(g+1,g+nn+1);
printf("%d\n",max(g[nn],g1));//输出
}
return 0;
}