CF #505 B Weakened Common Divisor
题意:问是否存在一个数,每组数据中都有数据可以整除它,并且这个数要大于1,如果存在多组数据随便输出一个,如果不存在,则输出-1。
这题一看到题目就想质因数分解。。然后写着写着。。很麻烦啊,而且,代码写的很乱,后来大佬提点,可以把一组里的两个数据相乘,然后求所有组数据积的最大公因数GCD,再把GCD质因数分解出最小的质数, GCD不一定使对的, 但是分解出来最小的质数肯定是对的, 但是因为数据太大,不能够打表到2e9,我只打表到2e5,但是对于大于2e5的素数就凉啊,然后,还有很多方面总是没考虑到,然后WA了无数次啊。。
思路:把每组数据的积求其最大公因数,再用质因数分解算出其最小质数。但是还有存在每组数据里两个数都是大于2e5(我打素数表的范围),我就凉了啊,所以添加一个步骤,把第一组数据质因数分解,算出其是否包含大于2e5的素数,如果没有分解完的数为1,则令其为2e9+10,就说明,答案一定是在我的打表范围内,如果不等于1,就是肯定存在大于2e5的素数,那么计算一下,后面的每组数据是否都存在这个因子,计算数量,如果数量等与n,则输出。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e5+10;
typedef long long ll;
ll p[maxn],num[maxn],k,a[maxn],b[maxn];
void prime(){
for(int i = 2; i < maxn; i++){
if(!num[i]){
for(ll j = 1LL*i*i; j < maxn; j+=i){
num[j] = 1;
}
}
}
k = 0;
for(int i = 2; i < maxn;i++){
if(!num[i])
p[++k] = i;
}
}
ll gcd(ll a,ll b){
return b == 0?a:gcd(b, a%b);
}
int main(){
int n;
ll x, y, a, b, sa, sb;
prime();
while(scanf("%d",&n)!=EOF){
scanf("%lld%lld",&x,&y);
num[1] = x*y;
if(n == 1){ //n等于1的时候先输出
printf("%lld\n",x);
continue;
}
for(int i = 1; i <= k&& x >= p[i]; i++){ //判断x中是否存在大于2e5的素数
while(x % p[i] == 0){
x /= p[i];
}
}
if(x == 1)
a = 2e9+10;
else
a = x;
for(int i = 1; i <= k&& y >= p[i]; i++){ //y与x 同理
while(y % p[i] == 0){
y /= p[i];
}
}
if(y == 1)
b = 2e9+10;
else
b = y;
sa = sb = 1;
for(int i = 2; i <= n; i++){
scanf("%lld%lld",&x,&y);
num[i] = x*y;
if(x % a == 0 || y % a == 0)
sa++;
if(y % b == 0|| x % b == 0)
sb++;
}
if(sa == n){
printf("%lld\n",a);
continue;
}
else if(sb == n){
printf("%lld\n",b);
continue;
}
ll Gcd = num[1];
for(int i = 2; i <= n; i++)
Gcd = gcd(num[i],Gcd);
int ans = 0;
for(int i = 1; i <= k;i++){
if(Gcd % p[i] == 0){
ans = p[i];
break;
}
}
if(ans == 0 && Gcd != 1)
printf("%lld\n",Gcd);
else if(ans == 0 && Gcd == 1)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}