UOJ#48. 【UR #3】核聚变反应强度 数学
显然,$sgcd(x,y)|gcd(x,y)$.
那么,$sgcd(x,y)=\frac{gcd(x,y)}{p[gcd(x,y)]}$
其中 $p[x]$ 表示 $x$ 的最小非 1 质因子.
那么我们可以先把 $gcd(a[1],a[i])$ 都求出来,然后枚举这个最小质因子.
因为 $gcd(a[1],a[i])$ 一定都是 $a[1]$ 的因数,所以只需要预处理 $a[1]$ 的所有质因子就行了.
然后由于一个数本质不同的质因子最多只有 $\log n$ 个,所以暴力枚举就行了.
code:
#include <bits/stdc++.h> #define N 100009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll a[N],b[N],g[N]; ll gcd(ll x,ll y) { return y?gcd(y,x%y):x; } char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) ll rd() { ll x=0; char c; while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x; } int main() { // setIO("input"); int n=(int)rd(),cnt=0; for(int i=1;i<=n;++i) a[i]=rd(); for(int i=1;i<=n;++i) g[i]=gcd(a[i],a[1]); ll x,y,z; for(int i=2;i<=1000000;++i) { if(a[1]%i==0) { b[++cnt]=i; while(a[1]%i==0) a[1]/=i; } } if(a[1]>1) b[++cnt]=a[1]; sort(b+1,b+1+cnt); for(int i=1;i<=n;++i) { int flag=0; for(int j=1;j<=cnt;++j) if(g[i]%b[j]==0) { printf("%lld ",g[i]/b[j]),flag=1; break; } if(!flag) printf("-1 "); } return 0; }