当前位置:   article > 正文

c++ 做题总结:质数及其筛法_c++质数筛

c++质数筛

网址:密码:hpuacm21级寒假集训——质数及其筛法 - Virtual Judgehttps://vjudge.csgrandeur.cn/contest/476396

一:质数的筛选方法

1.试除法

  1. bool isprimes(int n)
  2. {
  3. if (n == 1) return false;
  4. for (int i=2;i<=n/i;i++) {
  5. if (n % i == 0) return false;
  6. }
  7. return true;
  8. }

2.欧拉筛

  1. void get_primes(int n)
  2. {
  3. for (int i=2;i<=n;i++) {
  4. if (!st[i]) primes[cnt ++] = i;
  5. for (int j=0;primes[j]<=n/i;j++) {
  6. st[primes[j]*i] = 1;
  7. if (i%primes[j] == 0) break;
  8. }
  9. }
  10. }

二:具体题目的小知识点

1.题目E:回文质数

题解:

  1. #include<iostream>
  2. using namespace std;
  3. const int N = 1e7+7;
  4. int primes[N];
  5. bool st[N],st1[N];
  6. int cnt = 0;
  7. void get_primes(int n)
  8. {
  9. for (int i=2;i<=n;i++) {
  10. if (!st[i]) primes[cnt ++] = i;
  11. for (int j=0;primes[j]<=n/i;j++) {
  12. st[primes[j]*i] = 1;
  13. if (i%primes[j] == 0) break;
  14. }
  15. }
  16. }
  17. void init()
  18. {
  19. //a
  20. for (int i=1;i<10;i++) if (!st[i]) st1[i] = 1;
  21. st1[11] = 1;
  22. //aba
  23. for (int i=1;i<10;i++)
  24. for (int j=0;j<10;j++) st1[i*100+j*10+i] = 1;
  25. //abcba
  26. for (int i=1;i<10;i++)
  27. for (int j=0;j<10;j++)
  28. for (int k=0;k<10;k++) st1[i*10000+j*1000+k*100+j*10+i] = 1;
  29. //abcdcba
  30. for (int i=1;i<10;i++)
  31. for (int j=0;j<10;j++)
  32. for (int k=0;k<10;k++)
  33. for (int l=0;l<10;l++) st1[i*1000000+j*100000+k*10000+l*1000+k*100+j*10+i] = 1;
  34. }
  35. int main()
  36. {
  37. get_primes(N);init();
  38. int a,b;cin>>a>>b;
  39. for (int i=a;i<=b&&i<=10000000;i++) if (!st[i] && st1[i]) cout<<i<<endl;
  40. return 0;
  41. }

1.除了11以外,所有的回文质数的位数为偶数。

2.void init( ) 中的方法称为打表法:打表法就是将题⽬中需要的答案集合提前算出来,存到代码⾥,根据题⽬所需取答案,这种⽅法通常只需要 将程序挂着,在表打完后进⾏加⼯,最终取答案程序时间复杂度为O(1),空间复杂度为O(n)(n为答案规模); ——沃兹·基朔德 —— 摘⾃洛⾕。

3.可以用数组值作为存储数据的标记。

2.题目G:莫比乌斯函数

题解:

  1. #include<iostream>
  2. using namespace std;
  3. const int N = 1e8+8;
  4. int primes[N],mobius[N],cnt = 0;
  5. bool st[N];
  6. void init(int n)
  7. {
  8. mobius[1] = 1;
  9. for (int i=2;i<=n;i++) {
  10. if(!st[i]) primes[cnt++] = i,mobius[i] = -1;
  11. for (int j=0;primes[j]<=n/i;j++) {
  12. st[primes[j]*i] = 1;
  13. if (i%primes[j] == 0) break;
  14. mobius[primes[j]*i] -= mobius[i];
  15. }
  16. }
  17. }
  18. int main()
  19. {
  20. init(N);
  21. int n;
  22. while (cin>>n && n)
  23. {
  24. cout<<mobius[n]<<endl;
  25. }
  26. return 0;
  27. }

1.莫比乌斯函数可以用欧拉筛来求。

  已知唯一分解定理:x = p1^a1 * p2^a2 * p3^a3 * ...... * pn^an

  根据题意,需考虑三种情况:、

  (1)若x为1,则u(x) = 1;

  (2)若x为可以分解为异素数的乘积,则u(x) = (-1)^k;

  (3)若x分解的素数有重,则u(x) = 0;\

  这里可以用数组mobius[]来储存并标记;

3.欧拉筛与试除法的比较

欧拉筛虽然很快,但是储存空间过大,对于题目D ,H,I,用一般的试除法显然更快。

至于其中的原理,还要等到哪天我懂得更多的时候。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/75352
推荐阅读
相关标签
  

闽ICP备14008679号