如何学习这些毒瘤?

背模板!......反正学了不久就忘光了,还是背模板来的实在。

1.FFT

快速傅里叶变换。一切的基础。

作用是在 点值式 与 系数式 之间进行转换。

首先我们要手写复数。

然后背下来这个预处理的东西:

r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));

把n补全为2的次幂,下界为 n + m + 1,数组开4倍以上。

然后注意把n补全之后的各个地方n的写法:

FFT中都是 < n,涉及要实际输出的是 <= n 

最后别忘了 / n,输出时 + 0.5,输出 [0, n + m]

中间也要记清楚,Wn = (cos(pi / len), f * sin(pi / len));

手写pi的精度高一些,3.1415926 5358979 32384626

FFT前记得置换。

上代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cmath>
 4 const int N = 1000010;
 5 const double pi = 3.1415926535897932384626;
 6 
 7 struct cp {
 8     double x, y;
 9     cp(double tx = 0.0, double ty = 0.0) {
10         this->x = tx;
11         this->y = ty;
12     }
13     inline cp operator +(const cp &d) const {
14         return cp(x + d.x, y + d.y);
15     }
16     inline cp operator -(const cp &d) const {
17         return cp(x - d.x, y - d.y);
18     }
19     inline cp operator *(const cp &d) const { // 复数的乘法直接代数展开就能得到公式 
20         return cp(x * d.x - y * d.y, x * d.y + y * d.x);
21     }
22 }A[N << 2], B[N << 2]; // 空间开单个多项式的4倍
23 
24 int r[N << 2], n, lm;
25 
26 inline void init() {
27     while((1 << lm) < n) {
28         lm++;
29     }
30     n = 1 << lm;
31     for(int i = 1; i < n; i++) { // 这里从 0 或 1 开始,到 n 或 n - 1 都行 
32         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1)); // 背诵! 
33     }
34     return;
35 }
36 
37 inline void FFT(int n, cp *a, int f) {
38     for(int i = 0; i < n; i++) {
39         if(i < r[i]) {
40             std::swap(a[i], a[r[i]]); // 先转换 
41         }
42     }
43     for(int len = 1; len < n; len = len << 1) { // len 是倍增的 
44         cp Wn(cos(pi / len), f * sin(pi / len)); // 背诵!
45         for(int i = 0; i < n; i += (len << 1)) { // 加的是 (len << 1) !
46             cp w(1, 0);                          // 这里三个 < 没有 <= 
47             for(int j = 0; j < len; j++) {
48                 cp t = a[i + len + j] * w;
49                 a[i + len + j] = a[i + j] - t; /// error : t -> w
50                 a[i + j] = a[i + j] + t;
51                 w = w * Wn;
52             }
53         }
54     }
55     if(f == -1) {
56         for(int i = 0; i <= n; i++) {
57             a[i].x /= n; // 除n 
58         }
59     }
60     return;
61 }
62 
63 int main() {
64     int n1, n2;
65     scanf("%d%d", &n1, &n2);
66     for(int i = 0; i <= n1; i++) {
67         scanf("%lf", &A[i].x);
68     }
69     for(int i = 0; i <= n2; i++) {
70         scanf("%lf", &B[i].x);
71     }
72 
73     n = n1 + n2 + 1;
74     init();
75 
76     FFT(n, A, 1);
77     FFT(n, B, 1);
78     for(int i = 0; i <= n; i++) {
79         A[i] = A[i] * B[i];
80     }
81     FFT(n, A, -1);
82 
83     for(int i = 0; i <= n1 + n2; i++) {
84         printf("%d ", (int)(A[i].x + 0.5));
85     }
86 
87     return 0;
88 }
洛谷 P3803 AC代码

相关文章:

  • 2022-01-14
  • 2021-10-09
  • 2021-07-24
  • 2021-12-26
  • 2022-01-09
  • 2022-12-23
  • 2021-05-22
  • 2021-12-28
猜你喜欢
  • 2021-09-26
  • 2022-01-07
  • 2022-01-07
  • 2022-12-23
  • 2022-12-23
  • 2021-12-22
  • 2021-08-07
相关资源
相似解决方案