链接: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 中存放了到数字 i 为止的所有美素数个数,结果直接用左右边界做减法即可
原文地址:https://www.cnblogs.com/xxwang1018/p/11407234.html
时间: 2024-10-08 22:20:44