Prime triplets (Project Euler 196)

original version

hackerrank programming version

题目大意是定义了一个正整数的表,第一行是1,第二行是1,2,第三行1,2,3...定义prime triple是在表上八连通的三个质数。然后问某行有多少个质数至少在一个prime triple中。   行数 <= 1e7.

题解:

假设要求第n行的答案,只要把上2行和下2行的数都抠出来,然后判断一下就好了。问题转化为求[L,R]之间的质数,这里5行数,区间长度大概有5e7,所以要用modified 区间筛法。 参考 http://euler.stephan-brumme.com/196/ 。 没什么思维量,积累一个区间筛法模板。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 typedef long long LL;
  5 const int mod = 1e9 + 7;
  6 
  7 char* isPrime;
  8 LL bias;
  9 
 10 vector<LL> eratosthenesOddSingleBlock(LL from, LL to)
 11 {
 12     vector<LL> primes; 
 13     if (from > to || to <= 1) return primes;
 14     if (to == 2) 
 15     {
 16         primes.push_back(2);
 17         return primes;
 18     }
 19     if (!(from & 1)) ++from;
 20     if (from > to) return primes;
 21  
 22     if (from <= 2) primes.push_back(2), from = 3;
 23     const int memorySize = (to - from) / 2 + 1;
 24     char* isPrime = new char[memorySize];
 25 
 26   
 27     for (int i = 0; i < memorySize; i++)
 28         isPrime[i] = 1;
 29     for (LL i = 3; i*i <= to; i+=2)
 30     {
 31       if (i >= 3*3 && i % 3 == 0)
 32          continue;
 33       if (i >= 5*5 && i % 5 == 0)
 34          continue;
 35       if (i >= 7*7 && i % 7 == 0)
 36          continue;
 37       if (i >= 11*11 && i % 11 == 0)
 38          continue;
 39       if (i >= 13*13 && i % 13 == 0)
 40          continue;
 41       LL minJ = ((from+i-1)/i)*i;
 42       if (minJ < i*i)
 43           minJ = i*i;
 44       if ((minJ & 1) == 0)
 45           minJ += i;
 46       for (LL j = minJ; j <= to; j += 2*i)
 47       {
 48           int index = j - from;
 49           isPrime[index/2] = 0;
 50       }
 51     }
 52 
 53     for (int i = 0; i < memorySize; i++)
 54            if (isPrime[i]) primes.push_back(from + 2*i);
 55 
 56     delete[] isPrime;
 57     return primes;
 58 }
 59 
 60 
 61 bool checkPrime(LL val)
 62 {
 63     return isPrime[val - bias];
 64 }
 65 
 66 inline LL getNumber(int r, int c)
 67 {
 68     return 1LL * (r - 1) * r / 2 + c;
 69 }
 70 
 71 bool checkCentre(int r, int c)
 72 {
 73     if (c < 0 || c > getNumber(r, c) || !checkPrime(getNumber(r, c))) return false;
 74     int cnt = 0, x, y;
 75     for (int dx = -1; dx <= 1; ++dx)
 76     {
 77         for (int dy = -1; dy <= 1; ++dy)
 78         {
 79             x = r + dx;
 80             y = c + dy;
 81             if (y < 0 || y > x) continue;
 82             cnt += checkPrime(getNumber(x, y));
 83             if (cnt >= 3) return true;
 84         }
 85     }
 86     return false;
 87 }
 88 bool check(int r, int c)
 89 {
 90     for (int dx = -1; dx <= 1; ++dx)
 91         for (int dy = -1; dy <= 1; ++dy)
 92             if (checkCentre(r + dx, c + dy))
 93                return true;
 94     return false;
 95 }
 96 
 97 LL solve(int row)
 98 {
 99     if (row == 1) return 0;
100     if (row <= 3) return 5;
101     
102     LL l = getNumber(row - 2, 1), r = getNumber(row + 2, row + 2);
103     vector<LL> primes = eratosthenesOddSingleBlock(l, r);
104     isPrime = new char[r - l + 1];
105     memset(isPrime, 0, r - l + 1);
106     bias = l;
107     for (auto p: primes) isPrime[p - bias] = 1;
108     
109     pair<int, int> pos;
110     LL res = 0, val = getNumber(row, 1);
111     for (int col = 1; col <= row; ++col)
112     {
113         if (checkPrime(val) && check(row, col)) 
114            res += val;
115         ++val;
116     }
117     return res;
118 }
119 
120 int main()
121 {
122     //freopen("out.txt", "w" , stdout);
123     
124     int a, b;
125     cin >> a >> b; 
126     cout << solve(a) + solve(b) << endl;
127 
128     return 0;
129 }

猜你喜欢

转载自www.cnblogs.com/vb4896/p/9258846.html