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;
}

浙公网安备 33010602011771号