Weakened Common Divisor(cf div1+div2 B)
阿新 • • 發佈:2018-11-25
題目連結:
題意:
給定n對數,求一個WCD,它滿足至少能被每對數中的一個整除,若不存在,輸出-1。
思路:
一開始的思路是求每對數的最小公倍數,然後把這n個最小公倍數求個gcd,然後取其最小因子即可。但這樣因為TLE而FST了。後來想想也是,如果每對數中的兩個數互質,那麼他們的最小公倍數就是1e18左右的大小,求其最小因子的時間複雜度差不多就是1e9,肯定會T。比如下面這組樣例:
2
1999999973 1999999943
1999999973 1999999943
其實正解想法差不多,就把第一對中的第一個數和後面每對的乘積求一個gcd,第二個數也和後面的每對的乘積求一個gcd,這樣就保證這兩個數都是小於等於2e9的,求其最小因子的複雜度<1e5,可行。
PS:其實並不需要求每對數的最小公倍數,求其乘積即可,因為乘積包括了每對數那2個數中的所有因子,且乘積的最小因子一定能被每對數那2個數中的1個整除。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <set> #include <queue> #include <algorithm> 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; }