在期末被各科的大作业碾压快要窒息之际,百忙之中抽空上牛客网逛了逛,无意中发现一道好题,NowCoder猜想,题意很明显,就是个简单的素数筛法,但竟然超内存了,我晕(+﹏+)~ 明明有 3 万多 k 的空间限制……于是我不打表,试了试最暴力的做法,赤裸裸的做法果然超时了,无奈,只好对素数筛法进行位压缩了,这是我目前所能想到的方法了,第一次用上这样的特技,还是调了好一会(位数组里不能用 bool 来定义,具体的话好像 bool 和 int 之类的整型稍有不同;也不能用 int,因其最高位是正负标志位,所以只好用 unsigned int了,同样的原理,用 unsigned char, unsigned short, unsigned long long 等无符号整型都可以),贴个代码先,注释的为纯暴力:
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int inf = 0x3fffffff; 8 const int N = 1e7; 9 10 class bitarray { 11 unsigned int sign[320000]; 12 public: 13 bitarray() { memset(sign,0,sizeof(sign)); } 14 bool rid(const int &x) const { 15 return sign[x / 32] & (1 << (x % 32)); 16 } 17 void wid(const int &x, const int &v) { 18 sign[x / 32] |= (v ? (1 << (x % 32)) : 0); 19 } 20 }; 21 22 int pri[700005]; 23 int init_pri(int n = N) { 24 bitarray bit; 25 int c = 0; 26 for(int i = 2; i <= n; ++i) 27 if(!bit.rid(i)) { 28 pri[c++] = i; 29 for(int j = i << 1; j <= n; j += i) bit.wid(j,1); 30 } 31 return c; 32 } 33 34 /* 35 inline bool isprime(const int &x) { 36 if(x == 1) return 0; 37 int m = sqrt(x +0.5); 38 for(int i = 2; i <= m; ++i) 39 if(x % i == 0) return 0; 40 return 1; 41 } 42 43 inline int num(const int &n) { 44 int res = 0; 45 for(int i = 1; i <= n; i += 2) 46 if(isprime(i)) ++res; 47 return n >= 2 ? res + 1 : res; 48 } 49 */ 50 51 int main() { 52 int n,num = init_pri(); 53 pri[num++] = inf; 54 while(~scanf("%d",&n),n) { 55 int id = lower_bound(pri, pri+num, n) - pri; 56 if(pri[id] == n) printf("%d ",id + 1); 57 else printf("%d ",id); 58 } 59 return 0; 60 }
提交后发现无论是哪种做法,后台的内存计算都和我自己手算的差很远,不知它是怎么计算的。。。