[关闭]
@BIGBALLON 2015-05-07T12:48:27.000000Z 字数 2294 阅读 1526

LA 3998 Prime—k tuple

题意

给定 a,b(1<a<b<2000000000)
再给定 k,s 求区间[a,b]中有多少个k元组
k元组满足:共有k个相邻的素数,且第一个和最后一个素数的差值等于s

分析

先用筛法预处理出2000000000内的素数,
然后对于区间 [a,b] ,再用这些素数去暴力筛出其他的素数。
最后扫描一遍筛出的素数,确定答案。

这里,按照道理来说。。2000000000以内的素数有将近1亿个,但是开那么大的空间会RE,不知为何,最后开到的是 1000w 的数组

另外,这里也可以是,先筛出2000000000内的素数,其他的素数用米勒拉宾来判断。不过貌似并不是很快。。。

!!!!! 另外,,这里切记不要去使用mul(),,,我擦,,这样会极大程度得减慢miller rabin的速度,。

!!!!! 再另外,,题目没有给内存限制,,这也是一个很蛋疼的事

代码1

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define clr( a, b ) memset( a, b, sizeof(a) )
  5. #define SIZE 5000000
  6. int t, a, b, k, s, tot;
  7. int vis[ SIZE + 10 ], pri[ SIZE + 10 ], p[ 11000000 ];
  8. void init(){
  9. vis[0] = vis[1] = 1;
  10. int m = sqrt( SIZE + 0.5 );
  11. for( int i = 2; i <= m; ++i ) if( !vis[i] )
  12. for( int j = i * i; j <= SIZE; j += i ) vis[j] = 1;
  13. tot = 0;
  14. for( int i = 2; i <= SIZE; ++i ) if( !vis[i] )
  15. pri[ tot++ ] = i;
  16. }
  17. const int S = 8;
  18. LL fast_mod( LL a, LL b, LL M ){
  19. LL res = 1;
  20. while( b ){
  21. if( b & 1 ) res = res * a % M;
  22. a = a * a % M;
  23. b >>= 1;
  24. }
  25. return res;
  26. }
  27. bool miller_rabin( LL n ){
  28. if( n < 2 ) return false;
  29. if( n == 2 ) return true;
  30. if( !( n & 1 ) ) return false;
  31. int t = 0;
  32. LL cur, pre, u = n - 1;
  33. while( !( u & 1 ) ){
  34. t++;
  35. u >>= 1;
  36. }
  37. for( int i = 0; i < S; ++i ){
  38. LL a = rand() % ( n - 2 ) + 2;
  39. cur = fast_mod( a, u, n );
  40. pre = cur;
  41. for( int j = 0; j < t; ++j ){
  42. cur = pre * pre % n;
  43. if( cur == 1 && pre != 1 && pre != n - 1 )
  44. return false;
  45. pre = cur;
  46. }
  47. if( cur != 1 ) return false;
  48. }
  49. return true;
  50. }
  51. bool check( int x ){
  52. if( x <= SIZE ){
  53. return vis[x] == 0;
  54. }
  55. if( miller_rabin( 1LL * x ) ){
  56. return true;
  57. }else{
  58. return false;
  59. }
  60. }
  61. int main(){
  62. init();
  63. scanf( "%d", &t );
  64. srand( time( NULL ) );
  65. while( t-- ){
  66. scanf( "%d %d %d %d", &a, &b, &k, &s );
  67. int cnt = 0;
  68. for( int i = a; i <= b; ++i ){
  69. if( check(i) ){
  70. p[ cnt++ ] = i;
  71. }
  72. }
  73. int ans = 0;
  74. for( int i = 0; i < cnt - k + 1; ++i ){
  75. if( p[i+k-1] - p[i] == s ){
  76. ans++;
  77. }
  78. }
  79. printf( "%d\n", ans );
  80. }
  81. return 0;
  82. }

代码2

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define clr( a, b ) memset( a, b, sizeof(a) )
  5. #define SIZE 5000000
  6. int t, a, b, k, s, tot;
  7. int vis[ SIZE + 10 ], pri[ SIZE + 10 ], p[ 11000000 ];
  8. void init(){
  9. vis[0] = vis[1] = 1;
  10. int m = sqrt( SIZE + 0.5 );
  11. for( int i = 2; i <= m; ++i ) if( !vis[i] )
  12. for( int j = i * i; j <= SIZE; j += i ) vis[j] = 1;
  13. tot = 0;
  14. for( int i = 2; i <= SIZE; ++i ) if( !vis[i] )
  15. pri[ tot++ ] = i;
  16. }
  17. bool check( int x ){
  18. if( x <= SIZE ){
  19. return vis[x] == 0;
  20. }else{
  21. for( int i = 0; i < tot && pri[i] * pri[i] <= x; ++i ){
  22. if( x % pri[i] == 0 ){
  23. return false;
  24. }
  25. }
  26. }
  27. return true;
  28. }
  29. int main(){
  30. init();
  31. scanf( "%d", &t );
  32. while( t-- ){
  33. scanf( "%d %d %d %d", &a, &b, &k, &s );
  34. int cnt = 0;
  35. for( int i = a; i <= b; ++i ){
  36. if( check(i) ){
  37. p[ cnt++ ] = i;
  38. }
  39. }
  40. int ans = 0;
  41. for( int i = 0; i < cnt - k + 1; ++i ){
  42. if( p[i+k-1] - p[i] == s ){
  43. ans++;
  44. }
  45. }
  46. printf( "%d\n", ans );
  47. }
  48. return 0;
  49. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注