HDU 4548——美素数

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4548

题解

#include<cstring>
#include<iostream>
using namespace std;

const int n=1000005;
int prime[1000005];
bool vis[1000005];
int cnt[1000005]; //记录到数字 j为止的美素数个数 
void oula(){ //通过欧拉筛打表 
    int cnt=0;
    memset(prime,0,sizeof(prime));
    memset(vis,false,sizeof(vis));
    for(int t=2;t<=n;t++) { //枚举 t
        if(!vis[t]) //找到没有被删除的数 
            prime[cnt++]=t; //加入素数表 
        for(int j=0;j<cnt && t*prime[j]<=n;j++){ //枚举素数表 
            vis[t*prime[j]]=true; //标记 t和素数表相乘的合数 
            if(t%prime[j]==0) //如果遇到枚举的素数是 t的约数,跳出循环 
                break;
        }
    }
}
void beautfulprime(){
    cnt[0]=0;
    cnt[1]=0;
    for(int j=2;j<1000005;j++){
        cnt[j]=cnt[j-1]; //继承到上一个数字的美素数的个数,再计算当前数字是否满足要求
         
        long long sum=0;
        int k=j;
        while(k){
            sum+=k%10;
            k/=10;
        }
        if(vis[j]==false && vis[sum]==false) //数字 j是素数,其各位数字之和也是素数 
            cnt[j]++;
    }
}

int main() {
    int m;
    scanf("%d",&m);
    oula();
    beautfulprime();
    int l,r;
    for(int t=0; t<m; t++) {
        scanf("%d%d",&l,&r);
        printf("Case #%d: %lld\n",t+1,cnt[r]-cnt[l-1]);
    }
    return 0;
}

由于数字很大,需要打表以免超时

通过欧拉筛进行第一次打表,找出到右边界的所有素数,然后针对美素数的特点在得到的表格中进行第二次打表

数组 cnt 中存放了到数字 为止的所有美素数个数,结果直接用左右边界做减法即可

猜你喜欢

转载自www.cnblogs.com/xxwang1018/p/11407234.html