UVa 1404 - Prime k-tuple

contents

  1. 1. Problem
  2. 2. Sample Input
  3. 3. Sample Output
  4. 4. Solution

Problem

查找區間內,相鄰 k 個質數中,滿足最大減最小恰好為 s 的情況有多少個。

Sample Input

1
2
1
100 200 4 8

Sample Output

1
2

Solution

a, b 大小簡直不可思議,就算能做到全搜索,建表時間是線性,也必須跑上 20 億乘上 20。

先做一次 sieve,接著對 [a, b] 進行 local sieve,題目雖然沒說明 b - a 的大小,實際看來是非常小的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
using namespace std;
#define maxL (50000>>5)+1
#define MAXN (2000000000>>5)+1
#define GET(x) (mark[x>>5]>>(x&31)&1)
#define SET(x) (mark[x>>5] |= 1<<(x&31))
#define GET2(x) (mark2[x>>5]>>(x&31)&1)
#define SET2(x) (mark2[x>>5] |= 1<<(x&31))
int mark[maxL], mark2[MAXN];
int P[5500], Pt = 0;
void sieve() {
register int i, j, k;
SET(1);
int n = 50000;
for(i = 2; i <= n; i++) {
if(!GET(i)) {
for (k = n/i, j = i*k; k >= i; k--, j -= i)
SET(j);
P[Pt++] = i;
}
}
}
int local_sieve(int a, int b, int k, int s) {
int sqr = sqrt(b), gap = b - a;
memset(mark2, 0, ((gap>>5) + 1) * 4);
for (int i = 0; i < Pt && P[i] <= sqr; i++) {
int p = P[i], base = a / p * p;
while (base <= p) base += p;
for (int j = base; j <= b; j += p)
SET2(j - a);
}
if (a == 1) SET2(0);
queue<int> Q;
int ret = 0;
for (int i = 0; i <= gap; i++) {
if (!GET2(i)) {
if (Q.size() == k - 1) {
if (k == 0)
ret += s == 0;
else if ((a + i) - Q.front() == s)
ret++;
}
Q.push(a + i);
while (Q.size() >= k) Q.pop();
}
}
return ret;
}
int main() {
sieve();
int testcase;
int a, b, k, s;
scanf("%d", &testcase);
while (testcase--) {
scanf("%d %d %d %d", &a, &b, &k, &s);
printf("%d\n", local_sieve(a, b, k, s));
}
return 0;
}