• FFT总结


    对于一个多项式,如果我们能等到n个点值,就能求出多项式的各个系数

    所以对于$F(x) = f(x) * g(x)$, 可以通过求出n个f(x)的值进而求出F(x)的系数

    我们令这n个点分别为$ω_n^0, ω_n^1, ω_n^2 .... ,ω_n^n - 1$

    其中 $ω_n^n = 1, ω_n^frac{n}{2} = -1$

    而对于$f(ω_n^k)$, 我们有

    $$f(ω_n^k) = sumlimits_{i = 0}^{n - 1}a_i *ω_n^{ki} = sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i} *ω_n^{2ki}+ω_n^{k}sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i + 1} *ω_n^{2ki}$$

    $$=sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i} *ω_{frac{n}{2}}^{ki}+ω_n^{k}sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i + 1} *ω_{frac{n}{2}}^{ki}$$

    而对于$f(ω_n^{k + frac{n}{2}})$

    $$f(ω_n^{k + frac{n}{2}}) = sumlimits_{i = 0}^{n - 1}a_i *ω_n^{{(k+ frac{n}{2}})i} = sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i} *ω_n^{2ki}+ω_n^{k + frac{n}{2}}sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i + 1} *ω_n^{2ki}$$

    $$=sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i} *ω_{frac{n}{2}}^{ki}- ω_n^{k}sumlimits_{i = 0}^{frac{n}{2} - 1}a_{2i + 1} *ω_{frac{n}{2}}^{ki}$$

    于是发现

    $$f(ω_n^k) = u + v$$

    $$f(ω_n^{k + frac{n}{2}}) = u - v$$

    然后发现求出点值后,直接求逆就能得到多项式的系数,就像下面的图片所述。。。

    而u和v我们可以用同样的方法递归求解 这样是均摊(logn)的

    当然FFT是递归的常数是很大的,所以我们可以先预处理出来,这个学一学模板就好了

    有一个关于这个操作很详细的解释 补充——FFT中的二进制翻转问题

    至于NTT,如果模数是一个2 ^ n * k + 1之类的数,例如998244353, 我们可以令$ω_n^k = 3^{frac{p - 1}{n}k}$,剩下的操作是相同的。

    学会了理论,板子背一下就好了。  板子见下 :

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <complex>
     6 #include <algorithm>
     7 #define LL long long
     8 #define pi acos(-1)
     9 #define E complex<double>
    10 
    11 using namespace std;
    12 
    13 const int MAXN = 5e6 + 10;
    14 
    15 inline LL read()
    16 {
    17     LL x = 0, w = 1; char ch = 0;
    18     while(ch < '0' || ch > '9') {
    19         if(ch == '-') {
    20             w = -1;
    21         }
    22         ch = getchar();
    23     }
    24     while(ch >= '0' && ch <= '9') {
    25         x = x * 10 + ch - '0';
    26         ch = getchar();
    27     }
    28     return x * w;
    29 }
    30 
    31 E a[MAXN], b[MAXN];
    32 int n, m, L;
    33 int R[MAXN];
    34 
    35 void FFT(E *a, int f)
    36 {
    37     for(int i = 0; i < n; i++) {
    38         if(i < R[i]) {
    39             swap(a[i], a[R[i]]);
    40         }
    41     }
    42     for(int i = 1; i < n; i <<= 1) {
    43         E wn(cos(pi / i), f * sin(pi / i));
    44         for(int p = i << 1, j = 0; j < n; j += p) {
    45             E w(1, 0);
    46             for(int k = 0; k < i; k++, w *= wn) {
    47                 E x = a[j + k], y = w * a[j + k + i];
    48                 a[j + k] = x + y, a[j + k + i] = x - y;
    49             }
    50         }
    51     }
    52 }
    53 
    54 int main()
    55 {
    56     n = read(), m = read();
    57     for(int i = 0; i <= n; i++) {
    58         a[i] = read();
    59     }
    60     for(int i = 0; i <= m; i++) {
    61         b[i] = read();
    62     }
    63     m = n + m;
    64     for(n = 1; n <= m; n <<= 1) {
    65         L++;
    66     }
    67     for(int i = 0; i < n; i++) {
    68         R[i] = ((R[i >> 1] >> 1) | ((i & 1) << (L - 1)));
    69     }
    70     FFT(a, 1), FFT(b, 1);
    71     for(int i = 0; i < n; i++) {
    72         a[i] = a[i] * b[i];
    73     }
    74     FFT(a, -1);
    75     for(int i = 0; i <= m; i++) {
    76         printf("%d ", (int)(a[i].real() / n + 0.5));
    77     }
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    防止SSH自动断线
    php intval()和floatval()
    开启 intel vt-d
    前用户sudo免密码
    分区工具parted的详解及常用分区使用方法
    Proxmox qm命令应用实例
    Mac上制作Centos7系统U盘安装盘
    FinalShell Mac OS版,Linux版安装及教程
    python爬虫彩票案例,并自动发微信
    Python利用itchat库向好友或者公众号发消息
  • 原文地址:https://www.cnblogs.com/wuenze/p/8669993.html
Copyright © 2020-2023  润新知