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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
using cd = complex<double>;
const double PI = acos(-1.0);
const int MAXN = 1'000'000;
static void fft(vector<cd> &a, bool invert) {
int n = (int)a.size();
static vector<int> rev;
static vector<cd> roots{cd(0, 0), cd(1, 0)};
if ((int)rev.size() != n) {
int k = __builtin_ctz(n);
rev.assign(n, 0);
for (int i = 0; i < n; i++) {
rev[i] = 0;
for (int j = 0; j < k; j++) if (i & (1 << j))
rev[i] |= 1 << (k - 1 - j);
}
}
if ((int)roots.size() < n) {
int k = __builtin_ctz(roots.size());
roots.resize(n);
while ((1 << k) < n) {
double ang = 2 * PI / (1 << (k + 1));
for (int i = 1 << (k - 1); i < (1 << k); i++) {
roots[2 * i] = roots[i];
double a = ang * (2 * i + 1 - (1 << k));
roots[2 * i + 1] = cd(cos(a), sin(a));
}
k++;
}
}
for (int i = 0; i < n; i++)
if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int len = 1; len < n; len <<= 1) {
for (int i = 0; i < n; i += 2 * len) {
for (int j = 0; j < len; j++) {
cd u = a[i + j];
cd v = a[i + j + len] * roots[len + j];
a[i + j] = u + v;
a[i + j + len] = u - v;
}
}
}
if (invert) {
reverse(a.begin() + 1, a.end());
for (cd &x : a) x /= n;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Sieve up to MAXN
vector<bool> is_prime(MAXN + 1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i * 1LL * i <= MAXN; i++) {
if (is_prime[i]) {
for (int j = i * i; j <= MAXN; j += i) is_prime[j] = false;
}
}
// Prepare polynomial A: A[p] = 1 for all primes p (including 2)
int need = 1;
while (need < 2 * MAXN + 1) need <<= 1;
vector<cd> A(need, 0);
for (int i = 2; i <= MAXN; i++) if (is_prime[i]) A[i] = 1.0;
// Convolution A * A via FFT
fft(A, false);
for (int i = 0; i < need; i++) A[i] *= A[i];
fft(A, true);
// Round to nearest integer
vector<long long> conv(2 * MAXN + 1, 0);
for (int i = 0; i <= 2 * MAXN; i++) {
conv[i] = llround(A[i].real());
}
int T;
if (!(cin >> T)) return 0;
while (T--) {
int N; cin >> N; // even, 2 < N ≤ 1e6
// Ordered pairs from convolution = conv[N]
// Unordered count = (conv[N] + [N/2 is prime]) / 2
long long sym = (N % 2 == 0 && is_prime[N / 2]) ? 1 : 0;
long long ans = (conv[N] + sym) / 2;
cout << ans << '\n';
}
return 0;
}
|