这个题好纠结啊。
开始根本没有理解题意,最后才发现,p一定是质数,,,,,这个当时一直没发现。
已知n 和p的范围,
由素数算数基本定理得 n 能拆分程 x个素数之积。
n的因子个数为(a1+1)(a2+1).。。。
已知p为质数,所以 如果n为p的奇异数,则一定满足 n开p-1次方 一定是一个素数。
所以 当p>3 时, 情况不多,打表就行。
p=3时, 直接对n开方,在判断是否是素数就行。
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 31623, maxm = 17, maxp = 61;//sqrt(10^9) , 60以内素数个数 , ln(10^18)
const LL maxv = (LL)1e18,maxq=(LL)1e9;
int tot, pr[maxn], d[maxn], sz[maxm];
LL pp[maxm][maxn];
bool isprime(int x){ //判素
if(x<2) return 0;
if(x<maxn) return d[x] == x;
for(int i=0;i<tot&&pr[i]*pr[i]<=x;++i)
if(x%pr[i]==0) return 0;
return 1;
}
int main(){
tot=0;
for(int i=2; i<maxn; ++i){//快速线性筛法求素数
if(!d[i])
pr[tot++] = d[i] = i;
for(int j=0,k;(k=i*pr[j])<maxn;++j){
d[k]=pr[j];
if(!(d[i]%pr[j]))
break;
}
}
for(int i=2;i<maxm;++i){//打表
for(int j=0;j<tot;++j){
int rem=pr[i]-1;
LL val=1,lim=maxv/pr[j];
for( ;rem&&val<=lim;--rem,val*=pr[j]);
if(rem) break;
pp[i][sz[i]++] = val;
}
}
int t;
LL n, p;
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&n,&p);
if(p>=maxp||d[p]!=p){
puts("NO");
continue;
}
if(p==3){
LL val=(LL)sqrt(n);
puts(val*val==n&&isprime(val)?"YES":"NO");
continue;
}
for(int i=2;i<maxm;++i)
if(pr[i]==p){
puts(*std::lower_bound(pp[i],pp[i]+sz[i],n)==n?"YES":"NO");
break;
}
}
return 0;
}