本题大概可以算是线性筛算法的延伸。
如果之前还不屑知道线性筛,欢迎光临小蒟蒻的这篇关于线性筛模板和理解的博客。
题意:形如(4*k+1)的数被称为H数(k是非负数),如1,5,9……。除了自身和1以外没有一个H数因子的数被称为H素数,如125=5*5*5。只能分解成两个H素数之积的数被称为准H素数,如441=21*21。给出若干个数ai,求对于每个ai,1-ai中有多少个准H素数。
数据范围:1<=ai<=1e6+1。
我们知道,(4*a+1)*(4*b+1)=4*(4*a*b+b+a)+1。因此,两个H数相乘还是H数。那么,我们可以套用线性筛,O(n)求出H素数。如果能顺带求出准H素数,这道题就算解决了。我们知道,线性筛是对于每个H数x枚举H素数v,将x*v标记为非H素数。此时,我们只需判断x是否为H素数即可判断x*v是否是准H素数了。
一些细节处理详见代码:
1 #include <cstdio> 2 using namespace std; 3 const int sz=1e6+5; 4 int a[sz],mx,l,z[sz],len,h[sz],sum[sz]; 5 int main(){ 6 while(scanf("%d",&a[++l])){ 7 if(a[l]==0)break; 8 if(a[l]>mx)mx=a[l]; 9 } 10 for(int i=1;i<=(mx-1)/4;i++){ 11 sum[i]=sum[i-1]; 12 if(h[i]==0)z[++len]=i; 13 else if(h[i]==2)sum[i]++; 14 for(int j=1;j<=len&&(z[j]*4+1)*(i*4+1)<=mx;j++){ 15 h[4*z[j]*i+z[j]+i]=1; 16 if(h[i]==0)h[4*z[j]*i+z[j]+i]++; 17 if((i*4+1)%(z[j]*4+1)==0)break; 18 } 19 } 20 for(int i=1;i<l;i++) 21 printf("%d %d\n",a[i],sum[(a[i]-1)/4]); 22 return 0; 23 }
日常写错……欢迎指正
QQ:2960005671
邮箱:bleavescoder@163.com