kee*_*ing 8 c++ algorithm sieve-of-eratosthenes
我是这个论坛的新手,并不太了解这个论坛的协议,所以请原谅我的无知.我的问题与spoj问题https://www.spoj.pl/problems/KPRIMES2/有关.我正在为这个问题获得超时限制.我认为这个程序的瓶颈正在产生10 ^ 9.可能有人建议如何改进这个筛子,更快的方式来生成素数或如何解决这个问题.这是我算法的草图
该程序生成2k + 1形式的所有素数,并将这些素数编码为数组a [i]的32位整数,其中未设置位代表primes.a [0]编码3,5,7 ....... 65 .a [1]编码67以后,依此类推.我有一个辅助数组bitcnt [],其中bitcnt [i]存储[0],[1],......... a [i]的未设置位的总和.我使用bitcnt进行二分搜索并找到第k个数字的位置.这里是函数的位解释.prime()函数生成素数,并且我将素数编码到数字[32位无符号整数]的位上.bitcnt数组存储数组a的未设置位的总和,用于二进制搜索目的.bsearchupper(int m)返回m lie的bitcnt索引.最后在main函数中,我存储了多少素数到m的上限并开始递减值直到我得到K.谢谢.
编辑:SPOJ的问题陈述
输入
一个整数,表示查询数Q(等于100000),Q行跟随,每个包含1到50000000之间的一个整数K(含).
产量
Q行与每个查询的答案:Kth素数.
例
输入:8 1 10 100 1000 10000 100000 1000000 10000000
产量:2 29 541 7919 104729 1299709 15485863 179424673
#include<cstdio>
#include<vector>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#define Lim 1000000000
using namespace std;
unsigned int a[(Lim>>6)+10],bitcnt[(Lim>>6)+10];
int bound;
void prime()
{
int p_1,q_1,p_2,q_2,Ub=sqrt(Lim*1.0);
for(int i=3;i<=Ub;i+=2)
{
p_1=(i-3)>>6,q_1=((i-3)>>1)&31;
if(!(a[p_1] & (1L<<q_1)))
for(int j=i*i;j<Lim;j+=i)
if(j&1)
{
p_2=(j-3)>>6,q_2=((j-3)>>1)&31;
a[p_2]|=(1L<<q_2);
}
}
int cnt=0;bound=0;
for(int i=0; i<=((Lim>>6)-1);i++)
{
//p_1=(i-3)>>6,q_1=((i-3)>>1)&31;
cnt+=__builtin_popcount(~a[i]);
bitcnt[bound++]=cnt;
//cout<<bound-1<<"---"<<bitcnt[bound-1]<<endl;
}
//cout<<cnt<<endl;
}
int bsearchupper(int m)
{
int lo=0,hi=bound,mid;
while(lo<hi)
{
mid=lo+((hi-lo)>>1);
if(bitcnt[mid]<=m)lo=mid+1;
else hi=mid;
}
//cout<<"lo= "<<lo<<" mid= "<<mid<<" hi= "<<hi<<endl;
return lo;
}
int main()
{
//clock_t start,end;
//start=clock();
prime();
int t,k,c,ret,w;
for(scanf("%d",&t);t>0;t--)
{
scanf("%d",&k);
if(k==1) {cout<<"2"<<endl;continue;}
k=k-2;
c=bsearchupper(k);
ret=bitcnt[c],w=32*(c+1);
for(int i=31;i>=0;i--)
{
if(!(a[c] & (1L<<i)))
{
ret--;
if(ret==k) printf("%d\n",3+(w-1)*2);
}
w--;
}
}
//end=clock();
//cout<<((end-start)/(double)CLOCKS_PER_SEC)<<endl;
}
Run Code Online (Sandbox Code Playgroud)
考虑进一步压缩您的主要存储。例如,在 2*3*5*7*11=2310 的每个块中,正好有 1*2*4*6*10=480 个数字不具有 11 或更少的质因数,您可以将其打包为 15数组条目而不是(大约)36 个。这将消除筛选出这些小因素的几亿位操作。您必须更改位数组的索引;几个长度为 2310 的常量数组给出位索引(如果存在)和数组元素偏移量在这里会有所帮助,并且一个类似的数组(长度为 480)将位位置转换回模 2310 的值。