CF1366D 题解
题意简述
$n(1\le n\le2\times10^5)$ 次询问,每次给出正整数 $x(2\le x\le 10^7)$,要求判断是否存在 $x$ 的 $2$ 个不为 $1$ 的因数 $d_1,d_2$,使得 $\gcd(d_1+d_2,x)=1$,若存在则输出解,不存在输出 $-1$。
题目分析
比较好推的结论题。先给出结论:当且仅当 $x=p^k$($p$ 为质数,$k$ 为正整数)时,不存在符合条件的 $d_1,d_2$。
充分性证明:若 $x=p^k$($p$ 为质数,$k$ 为正整数),则对于所有的 $d|x$ 且 $d≠1$,有 $p|d$。因此 $p|(d_1+d_2)$,又有 $p|x$,则 $p|\gcd(d_1+d_2,x)$,得到 $\gcd(d_1+d_2,x)\ge p>1$。因此不存在符合条件的 $d_1,d_2$。
必要性证明:若 $x$ 不是质数的正整数次幂,则对其进行质因数分解得到 $x=p_1^{a_1}\times p_2^{a_2}\times\cdots\times p_k^{a_k}$。取 $d_1=p_i^{a_i}(1\le i\le k),d_2=\frac{x}{d_1}$,则 $\gcd(d_1,d_1+d_2)=\gcd(d_2,d_1+d_2)=\gcd(d_1,d_2)=1$。因此 $\gcd(d_1+d_2,x)=\gcd(d_1+d_2,d_1d_2)=1$,$d_1,d_2$ 满足题意。
有了这样一个结论,我们就只需要线性筛一下 $2\sim10^7$ 的所有质数。线性筛能顺便计算出每个数的最小质因数,所以每次根据 $x$ 的最小质因数 $p$ 判断 $x$ 是否是 $p$ 的正整数次幂即可。
代码实现
#include<bits/stdc++.h>
using namespace std;
int n,x,ans1[500010],ans2[500010],v[10000010],p[1000010],cnt,y;//v:最小质因数,p:质数
int main()
{
for(int i=2;i<=10000000;i++)
{
if(!v[i])
p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=10000000;j++)
{
v[i*p[j]]=p[j];
if(i%p[j]==0)
break;
}
}//线性筛
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(!v[x])//质数没预处理质因数,特判
ans1[i]=ans2[i]=-1;//无解
else
{
y=v[x];
while(y<=x/v[x]&&(x/y)%v[x]==0)//计算 p 的次数(其实可以优化,但是没必要)
y*=v[x];
if(x==y)
ans1[i]=ans2[i]=-1;//无解
else
ans1[i]=y,ans2[i]=x/y;
}
}
for(int i=1;i<=n;i++)
printf("%d ",ans1[i]);
printf("\n");
for(int i=1;i<=n;i++)
printf("%d ",ans2[i]);
return 0;
}