CF1366D 题解

题意简述

n(1n2×105) 次询问,每次给出正整数 x(2x107),要求判断是否存在 x2 个不为 1 的因数 d1,d2,使得 gcd(d1+d2,x)=1,若存在则输出解,不存在输出 1

题目分析

比较好推的结论题。先给出结论:当且仅当 x=pkp 为质数,k 为正整数)时,不存在符合条件的 d1,d2

充分性证明:若 x=pkp 为质数,k 为正整数),则对于所有的 d|xd1,有 p|d。因此 p|(d1+d2),又有 p|x,则 p|gcd(d1+d2,x),得到 gcd(d1+d2,x)p>1。因此不存在符合条件的 d1,d2

必要性证明:若 x 不是质数的正整数次幂,则对其进行质因数分解得到 x=p1a1×p2a2××pkak。取 d1=piai(1ik),d2=xd1,则 gcd(d1,d1+d2)=gcd(d2,d1+d2)=gcd(d1,d2)=1。因此 gcd(d1+d2,x)=gcd(d1+d2,d1d2)=1d1,d2 满足题意。

有了这样一个结论,我们就只需要线性筛一下 2107 的所有质数。线性筛能顺便计算出每个数的最小质因数,所以每次根据 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;
}
posted @   Hadtsti  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示