Description
这是一道模板题。
给你两个多项式,请输出乘起来后的多项式。
Input
第一行两个整数 $n$ 和 $m$,分别表示两个多项式的次数。
第二行 $n + 1$ 个整数,表示第一个多项式的 $0$ 到 $n$ 次项系数。
第三行 $m + 1$ 个整数,表示第二个多项式的 $0$ 到 $m$ 次项系数。
Output
一行 $n + m + 1$ 个整数,表示乘起来后的多项式的 $0$ 到 $n + m$ 次项系数。
Sample Input
1 2
1 2
1 2 1
Sample Output
1 4 5 2
Sample Explanation
$(1 + 2x) cdot (1 + 2x + x^2) = 1 + 4x + 5x^2 + 2x^3$。
HINT
$0 leq n, m leq 10^5$,保证输入中的系数大于等于 $0$ 且小于等于 $9$。
时间限制:$1 exttt{s}$
空间限制:$256 exttt{MB}$
题解
终于会背模板 $FFT$ 辣!!
1 //It is made by Awson on 2018.1.27 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <complex> 14 #include <iostream> 15 #include <algorithm> 16 #define LL long long 17 #define dob complex<double> 18 #define Abs(a) ((a) < 0 ? (-(a)) : (a)) 19 #define Max(a, b) ((a) > (b) ? (a) : (b)) 20 #define Min(a, b) ((a) < (b) ? (a) : (b)) 21 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 22 #define writeln(x) (write(x), putchar(' ')) 23 #define lowbit(x) ((x)&(-(x))) 24 using namespace std; 25 const int INF = ~0u>>1; 26 const double pi = acos(-1.0); 27 const int N = 1e5*4; 28 void read(int &x) { 29 char ch; bool flag = 0; 30 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); 31 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 32 x *= 1-2*flag; 33 } 34 void write(int x) { 35 if (x > 9) write(x/10); 36 putchar(x%10+48); 37 } 38 39 int n, m, x, L, R[N+5]; 40 dob a[N+5], b[N+5]; 41 42 void FFT(dob *A, int o) { 43 for (int i = 0; i < n; i++) if (i > R[i]) swap(A[i], A[R[i]]); 44 for (int i = 1; i < n; i <<= 1) { 45 dob wn(cos(pi/i), sin(pi*o/i)), x, y; 46 for (int j = 0; j < n; j += (i<<1)) { 47 dob w(1, 0); 48 for (int k = 0; k < i; k++, w *= wn) { 49 x = A[j+k], y = w*A[i+j+k]; 50 A[j+k] = x+y, A[i+j+k] = x-y; 51 } 52 } 53 } 54 } 55 void work() { 56 read(n), read(m); 57 for (int i = 0; i <= n; i++) read(x), a[i] = x; 58 for (int i = 0; i <= m; i++) read(x), b[i] = x; 59 m += n; 60 for (n = 1; n <= m; n <<= 1) L++; 61 for (int i = 0; i < n; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1)); 62 FFT(a, 1), FFT(b, 1); 63 for (int i = 0; i < n; i++) a[i] *= b[i]; 64 FFT(a, -1); 65 for (int i = 0; i <= m; i++) write(int(a[i].real()/n+0.5)), putchar(' '); 66 } 67 int main() { 68 work(); 69 return 0; 70 }
upd 18.4.2:
$NTT$ 的板子:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int mod = 998244353; 4 const int N = 4e5; 5 6 int n, m, a[N+5], b[N+5], x, L, R[N+5]; 7 8 int quick_pow(int a, int b) { 9 int ans = 1; 10 while (b) { 11 if (b&1) ans = 1ll*ans*a%mod; 12 b >>= 1, a = 1ll*a*a%mod; 13 } 14 return ans; 15 } 16 void NTT(int *A, int o) { 17 for (int i = 0; i < n; i++) if (i < R[i]) swap(A[i], A[R[i]]); 18 for (int i = 1; i < n; i <<= 1) { 19 int gn = quick_pow(3, (mod-1)/(i<<1)), x, y; 20 if (o == -1) gn = quick_pow(gn, mod-2); 21 for (int j = 0; j < n; j += (i<<1)) { 22 int g = 1; 23 for (int k = 0; k < i; k++, g = 1ll*g*gn%mod) { 24 x = A[j+k], y = 1ll*g*A[j+k+i]%mod; 25 A[j+k] = (x+y)%mod; 26 A[j+k+i] = (x-y+mod)%mod; 27 } 28 } 29 } 30 } 31 void work() { 32 scanf("%d%d", &n, &m); 33 for (int i = 0; i <= n; i++) scanf("%d", &x), a[i] = x; 34 for (int i = 0; i <= m; i++) scanf("%d", &x), b[i] = x; 35 m += n; 36 for (n = 1; n <= m; n <<= 1) ++L; 37 for (int i = 0; i < n; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1)); 38 NTT(a, 1), NTT(b, 1); 39 for (int i = 0; i < n; i++) a[i] = 1ll*a[i]*b[i]%mod; 40 NTT(a, -1); 41 int inv = quick_pow(n, mod-2); 42 for (int i = 0; i <= m; i++) printf("%d ", int(1ll*a[i]*inv%mod)); 43 } 44 int main() {work(); return 0; }