|
| 1 | +#include <cstdio> |
| 2 | +#include <cassert> |
| 3 | +#include <algorithm> |
| 4 | + |
| 5 | +namespace NTT { |
| 6 | + using ll = long long; |
| 7 | + const ll P = 2013265921, g = 31; |
| 8 | + //2113929217,5; 1811939329,13; 2130706433,3; 786433,10; |
| 9 | + //1945555039024054273,5; 1231453023109121ll,3; |
| 10 | + inline ll mul_mod(ll a, ll b, ll mod) { |
| 11 | + assert(0 <= a && a < mod); |
| 12 | + assert(0 <= b && b < mod); |
| 13 | + if (mod < int(1e9)) return a * b % mod; |
| 14 | + ll k = (ll)((long double)a * b / mod); |
| 15 | + ll res = a * b - k * mod; |
| 16 | + res %= mod; |
| 17 | + if (res < 0) res += mod; |
| 18 | + return res; |
| 19 | + } |
| 20 | + ll pow_mod(ll a, ll n, ll m) { |
| 21 | + ll r = 1; |
| 22 | + for (; n; n >>= 1) { |
| 23 | + if (n & 1) r = mul_mod(r, a, m); |
| 24 | + a = mul_mod(a, a, m); |
| 25 | + } |
| 26 | + return r; |
| 27 | + } |
| 28 | + void trans(ll a[], int n, bool inv = false) { |
| 29 | + ll w = 1, d = pow_mod(g, (P - 1) / n, P), t; |
| 30 | + int i, j, c, s; |
| 31 | + if (inv) { |
| 32 | + for (i = 1, j = n - 1; i < j; std::swap(a[i++], a[j--])); |
| 33 | + for (t = pow_mod(n, P - 2, P), i = 0; i < n; ++i) { |
| 34 | + a[i] = mul_mod(a[i], t, P); |
| 35 | + } |
| 36 | + } |
| 37 | + for (s = n >> 1; s; s >>= w = 1, d = mul_mod(d, d, P)) { |
| 38 | + for (c = 0; c < s; ++c, w = mul_mod(w, d, P)) { |
| 39 | + for (i = c; i < n; i += s << 1) { |
| 40 | + t = a[i | s]; |
| 41 | + a[i | s] = mul_mod((a[i] + P - t) % P, w, P); |
| 42 | + a[i] = (a[i] + t) % P; |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + for (i = 1; i < n; ++i) { |
| 47 | + for (j = 0, s = i, c = n >> 1; c; c >>= 1, s >>= 1) { |
| 48 | + j = j << 1 | s & 1; |
| 49 | + } |
| 50 | + if (i < j) std::swap(a[i], a[j]); |
| 51 | + } |
| 52 | + } |
| 53 | +} |
0 commit comments