zstuoj 4274 约素


点击打开链接


由素数算数基本定理得  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;  
}  

现场的代码:


#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=111;
const int S = 50;
int a[32222];
int main(){
    a[0]=a[1]=1;
    for(int i=2;i<32000;++i){
        if(!a[i])
        for(int j=i+i;j<32000;j+=i)
            a[j]=1;
    }
    int T;
    ll n,p;
    scanf("%d",&T);
    while(T--){
        scanf("%lld %lld",&n,&p);
        int cnt=0,f=0;
        if(p==3) {
            int ss=0;
            int t=sqrt(n);
            if(t*t==n) ss=1;
            if(ss==1) printf("YES\n");
            else printf("NO\n");
            continue;
        }
        for(int i=2;i<32000;++i){
            if(a[i]==0&&n%i==0) {
                if(n==pow(i,p-1)) f=1;
                break;
            }
        }
        if(f) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值