传送门:HDU 3826
题目大意:
判断一个数 n (2<= n <= 10e18)的所有因子中是否包含平方数。
思路:
根据唯一分解定理我们可以知道,任何整数都可以分解成多个质数的乘积。本题也就成了求一个数 n 是否是 p*p 的倍数,其中 p 是质数。由于 n 的范围,所以 p 最大是 10e9,这个范围太大,我们是无法通过筛选法打表的。
换种思路,我们先求出 2~10e6 范围内的所有质数,将 n 质数分解后看看有没有哪个质数的幂大于等于 2,如果大于等于 2,则说明含有平方数。否则,n 不断除以 2~10e6 范围内的质数后的结果要么是 1,要么是一个大于 10e6 的数。如果是后一种情况,我们则将 n 开方,然后看看 n 是否是这个开方后结果的平方。
你可能会问,为什么通过判断 n 是否是开方后结果的平方就可以判断是否含有平方因子。因为通过质数分解,我们已经把 2~10e6 之内的质因子都去除了,剩下的因子一定比 10e6 大,而因子(可相同)个数最多不超过 2,因为如果是 3,则 n 就一定比 10e18 大了。
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
typedef long long LL;
int tol,p[100000],pri[1000010];
void prime()
{ //筛选法求 1~10e6内的质数
int i,j;
tol=0;
memset(pri,1,sizeof(pri));
for(i=2;i<=1000000;i++)
if(pri[i])
{
p[tol++]=i;
for(j=2*i;j<=1000000;j+=i) pri[j]=0;
}
}
int main()
{
int t,f,num,cas;
LL i,n,x;
cas=1;
prime();
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
f=0;
for(i=0;i<tol;i++)
{ //遍历 10e6内的每个质数
num=0;
while(n%p[i]==0)
{
n/=p[i];
num++; //质因子个数
}
if(num>=2)
{ //如果质因子个数 >=2,则含有平方因子
f=1;
break;
}
}
if(n!=1)
{ //如果 n !=1且 n是开方后的结果的平方
x=sqrt(n);
if(x*x==n) f=1;
}
if(!f) printf("Case %d: Yes\n",cas++);
else printf("Case %d: No\n",cas++);
}
return 0;
}