P8842 [传智杯 #4 初赛] 小卡与质数2
Adolfo_North · · 题解
传送门
变态数学题(主考位运算与素数筛)。
读完题看起来有点难做,因为质数的出现是根本没有可以使用的规律。暴力的话也很好想,枚举
再思考一下,
注意下面的步骤需要草稿纸推演,不然会有点难理解。
我们设符合条件的素数为
随即。我们用素数筛,并统计范围内所有素数的最高位是哪一位,对于每个询问把
代码奉上:
#include<iostream>
using namespace std;
int T,n,m,ans;
int zhi[2000010],cnt[26];
bool f[2000010];
void IAKchuanzhibei(){
//素数筛 (欧拉筛法)
for(int i=2;i<=2000000;i++){
if(!f[i])zhi[++m]=i;
for(int j=1;j<=m&&i*zhi[j]<=2000000;j++){
f[i*zhi[j]]=1;
if(!(i%(zhi[j])))break;
}
}
//开桶记录
for(int i=1;i<=m;i++)
for(int j=25;j>=1;j--)//由于1000000内最大的质数为999983,转成二进制为1111 0100 0010 0010 1111,共24位,为保险起见,这里从25开始计算
if(zhi[i]&(1<<(j-1))){
cnt[j]++;//计算当质数为j位时,一共的个数
break;
}
}
int main()
{
//预处理
IAKchuanzhibei();
cin>>T;
while(T--)
{
cin>>n;
ans=0;
for(int i=25;i>=1;i--) if(n&(1<<(i-1))) ans+=cnt[i];//加上所有符合条件的素数
cout<<ans<<endl;
}
return 0;
}
证明过程:
观点一:那么
观点二:那么重点来到
我们设