题目链接:
B. Weakened Common Divisor
题意:
给定n对数,求一个WCD,它满足至少能被每对数中的一个整除,若不存在,输出-1。
思路:
一开始的思路是求每对数的最小公倍数,然后把这n个最小公倍数求个gcd,然后取其最小因子即可。但这样因为TLE而FST了。后来想想也是,如果每对数中的两个数互质,那么他们的最小公倍数就是1e18左右的大小,求其最小因子的时间复杂度差不多就是1e9,肯定会T。比如下面这组样例:
2
1999999973 1999999943
1999999973 1999999943
其实正解想法差不多,就把第一对中的第一个数和后面每对的乘积求一个gcd,第二个数也和后面的每对的乘积求一个gcd,这样就保证这两个数都是小于等于2e9的,求其最小因子的复杂度<1e5,可行。
PS:其实并不需要求每对数的最小公倍数,求其乘积即可,因为乘积包括了每对数那2个数中的所有因子,且乘积的最小因子一定能被每对数那2个数中的1个整除。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int MAX = 150000 + 10;
const ll mod = 1e9 + 7;int n;ll gcd(ll m, ll n)
{while (m>0){ll c = n % m;n = m;m = c;}return n;
}inline ll read() {char ch = getchar(); ll x = 0, f = 1;while(ch < '0' || ch > '9') {if(ch == '-') f = -1;ch = getchar();} while('0' <= ch && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();} return x * f;
}ll solve(ll x)
{for (ll i = 2; i*i <= x; i++) {if (x%i == 0) {return i;}}return x;
}int main()
{n=read();ll a, b;a=read();b=read();if (n == 1) {printf("%lld\n", a);return 0;}int cnt=0;ll ans1,ans2;ans1=a; ans2=b;for (int i = 1; i < n; i++) {ll x, y;x=read();y=read();ll g = x*y;ans1 = gcd(ans1, g);ans2 = gcd(ans2, g);}if(ans1!=1){ll ans=solve(ans1);printf("%lld\n",ans);}else if(ans2!=1){ll ans=solve(ans2);printf("%lld\n",ans);}else{printf("-1\n");}return 0;
}