令
f
(
x
)
=
a
0
+
a
1
x
+
a
2
x
2
+
a
3
x
3
+
a
4
x
4
+
a
5
x
5
+
a
6
x
6
+
a
7
x
7
f(x)=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7
f(x)=a0+a1x+a2x2+a3x3+a4x4+a5x5+a6x6+a7x7;
w
4
=
−
1
w^4=-1
w4=−1
f
(
w
0
)
=
[
(
a
0
+
a
4
)
+
(
a
2
+
a
6
)
]
+
[
(
a
1
+
a
5
)
+
(
a
3
+
a
7
)
]
f(w^0)=[(a_0+a_4)+(a_2+a_6)]+[(a_1+a_5)+(a_3+a_7)]
f(w0)=[(a0+a4)+(a2+a6)]+[(a1+a5)+(a3+a7)]
f
(
w
4
)
=
[
(
a
0
+
a
4
)
+
(
a
2
+
a
6
)
]
−
[
(
a
1
+
a
5
)
+
(
a
3
+
a
7
)
]
f(w^4)=[(a_0+a_4)+(a_2+a_6)]-[(a_1+a_5)+(a_3+a_7)]
f(w4)=[(a0+a4)+(a2+a6)]−[(a1+a5)+(a3+a7)]
//
f
(
w
1
)
=
[
(
a
0
−
a
4
)
+
(
a
2
−
a
6
)
w
2
]
+
[
(
a
1
−
a
5
)
w
+
(
a
3
−
a
7
)
w
3
]
f(w^1)=[(a_0-a_4)+(a_2-a_6)w^2]+[(a_1-a_5)w+(a_3-a_7)w^3]
f(w1)=[(a0−a4)+(a2−a6)w2]+[(a1−a5)w+(a3−a7)w3]
f
(
w
5
)
=
[
(
a
0
−
a
4
)
+
(
a
2
−
a
6
)
w
2
]
−
[
(
a
1
−
a
5
)
w
+
(
a
3
−
a
7
)
w
3
]
f(w^5)=[(a_0-a_4)+(a_2-a_6)w^2]-[(a_1-a_5)w+(a_3-a_7)w^3]
f(w5)=[(a0−a4)+(a2−a6)w2]−[(a1−a5)w+(a3−a7)w3]
//
f
(
w
2
)
=
[
(
a
0
+
a
4
)
−
(
a
2
+
a
6
)
]
+
[
(
a
1
+
a
5
)
−
(
a
3
+
a
7
)
]
w
2
f(w^2)=[(a_0+a_4)-(a_2+a_6)]+[(a_1+a_5)-(a_3+a_7)]w^2
f(w2)=[(a0+a4)−(a2+a6)]+[(a1+a5)−(a3+a7)]w2
f
(
w
6
)
=
[
(
a
0
+
a
4
)
−
(
a
2
+
a
6
)
]
−
[
(
a
1
+
a
5
)
−
(
a
3
+
a
7
)
]
w
2
f(w^6)=[(a_0+a_4)-(a_2+a_6)]-[(a_1+a_5)-(a_3+a_7)]w^2
f(w6)=[(a0+a4)−(a2+a6)]−[(a1+a5)−(a3+a7)]w2
//
f
(
w
3
)
=
[
(
a
0
−
a
4
)
−
(
a
2
−
a
6
)
w
2
]
+
[
(
a
1
−
a
5
)
w
−
(
a
3
−
a
7
)
w
3
]
w
2
f(w^3)=[(a_0-a_4)-(a_2-a_6)w^2 ]+[(a_1-a_5)w -(a_3-a_7)w^3]w^2
f(w3)=[(a0−a4)−(a2−a6)w2]+[(a1−a5)w−(a3−a7)w3]w2
f
(
w
7
)
=
[
(
a
0
−
a
4
)
−
(
a
2
−
a
6
)
w
2
]
−
[
(
a
1
−
a
5
)
w
−
(
a
3
−
a
7
)
w
3
]
w
2
f(w^7)=[(a_0-a_4)-(a_2-a_6)w^2 ]-[(a_1-a_5)w -(a_3-a_7)w^3]w^2
f(w7)=[(a0−a4)−(a2−a6)w2]−[(a1−a5)w−(a3−a7)w3]w2
//
第一层
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
class Ntt {
public:
LL w;
LL p;
LL n;
LL len;
vector<LL> W;
vector<LL> rev;
Ntt(LL w, LL p,LL n) {
this->w = w;
this->p = p;
this->n = n;
this->len = 1LL << n;
W.resize(len);
rev.resize(len);
rw.resize(len);
rev[0] = 0;
W[0] = 1;
for (int i = 1; i < len; i++) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (n - 1));
W[i] = W[i - 1] * w % p;
}
rwf();
}
void rwf() {
rw[0] = 1;
auto r = W[7] % p;
for (int i = 1; i < len; i++)rw[i] = rw[i - 1] * r % p;
}
void gsNtt(LL a[]) {
LL wk = w%p;
for (int mid = len >> 1; mid > 0; mid >>= 1) {
for (int j = 0; j + mid*2 <= len; j += mid*2) {
LL wi = 1;
for (int i = j; i < j+mid; i++) {
auto tmp = (a[i] + a[i + mid]) % p;
a[i + mid] = (a[i] - a[i + mid]) * wi % p;
a[i] = tmp;
while (a[i + mid] < 0)a[i + mid] += 17;
while (a[i] < 0)a[i] += 17;
wi = wi * wk % p;
}
}
for (int i = 0; i < 8; i++)cout << a[i] << ' ';
cout << endl;
wk = wk * wk % p;
}
}
vector<LL> rw;
void gsINTT(LL a[]) {
int pos = len >> 1;
LL wk = rw[pos];
for (int mid = 1; mid <= len/2; mid<<=1) {
for (int j = 0; j + mid * 2 <= len; j += mid * 2) {
LL wi = 1;
for (int i = j; i < j + mid; i++) {
auto L = a[i];
auto R = a[i + mid];
R = R * wi % p;
a[i] = (L + R) *W[7] % p;
a[i + mid] = (L - R) * W[7] % p;
while (a[i + mid] < 0)a[i + mid] += 17;
while (a[i] < 0)a[i] += 17;
wi = wi * wk % p;
}
}
for (int i = 0; i < 8; i++)cout << a[i] << ' ';
cout << endl;
pos >>= 1;
wk = rw[pos];
}
}
};
int main() {
Ntt tmp(2, 17, 3);
LL a[8] = { 1LL,2LL,3LL,7LL,1LL,6LL,7LL,8LL };
tmp.gsNtt(a);
for (int i = 0; i < 8; i++) {
cout << a[i] << ' ';
}cout << endl;
tmp.gsINTT(a);
for (int i = 0; i < 8; i++) {
cout << a[i] << ' ';
}cout << endl;
}