luogu3803 多项式乘法 (FFT)

FFT讲解传送门

简单记一下做法:

  1.算法流程:两式的系数表达转化为点值表达(O(nlogn))->利用点值表达使两式相乘(O(n))->将结果的点值表达转化回系数表达(O(nlogn))

  2.做法:

    $$目标:把一个n项多项式F(x)=\sum_{i=0}^{n-1}a_ix^i转化为\{(w^k_n,y_k)\}的点值表达,其中w^k_n为n次单位根的k次方$$

    不妨设n为2的幂次,如果不是,则可以补上系数为0的高次项

    $$将a_ix^i按照幂次奇偶性分组,得到F(x)=(a_0x^0+a_2x^2+...+a_{n-2}x^{n-2})+(a_1x^1+a_3x^3..a_{n-1}x^{n-1})$$

    $$设F_0(x)=a_0x^0+a_2x^1+a_4x^2+...+a_{n-2}x^{frac{n}{2}-1} , F_1(x)=a_1x^0+a_3x^1+a_5x^2+...+a_{n-1}x^{frac{n}{2}-1}$$

    $$则F(x)=F_0(x^2)+xF_1(x^2)$$

    $$带入n次单位根,F(w^k_n)=F_0(w^{2k}_n)+w^k_nF_1(w^{2k}_n)$$

    $$w^{xk}_{xn}=w^k_n  ==> F(w^k_n)=F_0(w^k_{\frac{n}{2}})+w^k_nF_1(w^k_{\frac{n}{2}}) $$

    $$w^{k}_{n}=-w^{k+\frac{n}{2}}_n ==> F(w^{k+\frac{n}{2}}_n)=F_0(w^k_{\frac{n}{2}})-w^k_nF_1(w^k_{\frac{n}{2}}) $$

剩下明天写(2018-07-25)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define LL long long int
 6 using namespace std;
 7 const int maxn=2097152;
 8 const double Pi=acos(-1);
 9
10 LL rd(){
11     LL x=0;int neg=1;char c=getchar();
12     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
13     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
14     return x*neg;
15 }
16
17 struct Complex{
18     double x,y;
19     Complex(double x0=0,double y0=0){x=x0,y=y0;}
20 }A[maxn],B[maxn];
21 Complex operator * (Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
22 Complex operator + (Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
23 Complex operator - (Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
24 int rev[maxn],N,M,len=1;
25
26 void fft(Complex *a,int opt){
27     for(int i=0;i<len;i++){
28         if(i<rev[i]) swap(a[i],a[rev[i]]);
29     }
30     for(int i=1;i<len;i<<=1){
31         Complex wn=Complex(cos(Pi/i),opt*sin(Pi/i));
32         int step=i<<1;
33         for(int j=0;j<len;j+=step){
34             Complex w=Complex(1,0);
35             for(int k=0;k<i;k++,w=w*wn){
36                 Complex x=a[j+k];
37                 Complex y=w*a[j+k+i];
38                 a[j+k]=x+y;
39                 a[j+k+i]=x-y;
40             }
41         }
42     }
43 }
44
45 int main(){
46     int i,j,k;
47     N=rd()+1,M=rd()+1;
48     for(i=0;i<N;i++) A[i].x=rd();
49     for(i=0;i<M;i++) B[i].x=rd();
50     k=0;while(len<N+M-1) len<<=1,k++;
51     for(i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
52     fft(A,1);fft(B,1);
53     for(i=0;i<len;i++) A[i]=A[i]*B[i];
54     fft(A,-1);
55     for(i=0;i<N+M-1;i++){
56         printf("%d ",(int)(A[i].x/len+0.5));
57     }
58     return 0;
59 }

原文地址:https://www.cnblogs.com/Ressed/p/9368463.html

时间: 2024-11-07 16:52:17

luogu3803 多项式乘法 (FFT)的相关文章

多项式乘法(FFT)学习笔记

------------------------------------------本文只探讨多项式乘法(FFT)在信息学中的应用如有错误或不明欢迎指出或提问,在此不胜感激 多项式 1.系数表示法     一般应用最广泛的表示方式     用A(x)表示一个x-1次多项式,a[i]为$ x^i$的系数,则A(x)=$ \sum_0^{n-1}$ a[i] * $ x^i$ 仅利用这种方式求多项式乘法复杂度为O($ n^2$),不够优秀2.点值表示法     将n个互不相同的值$ x_0$...$

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

[uoj#34] [洛谷P3803] 多项式乘法(FFT)

新技能--FFT. 可在 \(O(nlogn)\) 时间内完成多项式在系数表达与点值表达之间的转换. 其中最关键的一点便为单位复数根,有神奇的折半性质. 多项式乘法(即为卷积)的常见形式: \[ C_n=\sum\limits_{i=0}^n A_iB_{n-i} \] 基本思路为先将系数表达 -> 点值表达 \(O(nlogn)\) 随后点值 \(O(n)\) 进行乘法运算 最后将点值表达 -> 系数表达 \(O(nlogn)\) 代码 #include<cstdio> #inc

UOJ #34 多项式乘法 FFT快速傅立叶变换

题目大意:这是一道模板题. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 using namespace std; const double PI = acos(-1.0); struct Complex{ double x,y; Complex(dou

【模版】多项式乘法 FFT

https://www.luogu.org/problem/show?pid=3803 题目背景 这是一道模版题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 1 2 1 2 1

[HDU4609] 3-idiots - 多项式乘法,FFT

题意:有\(n\)个正整数,求随机选取一个3组合,能构成三角形的概率. Solution: 很容易想到构造权值序列,对其卷积得到任取两条边(可重复)总长度为某数时的方案数序列,我们希望将它转化为两条边不可重复,并去掉顺序.不妨设给定的 \(N\) 个正整数的集合为 \(S\),卷积后的权值序列为 \(\{c_i\}\) ,那么我们对每一个 \(x \in S\), 对 \(c_x\) 减去 \(1\) 即可. 不妨设选出的组合为 \((i,j,k)\),假设 \({x_i}\) 为已经排序的长度

LibreOJ #108. 多项式乘法

二次联通门 : LibreOJ #108. 多项式乘法 /* LibreOJ #108. 多项式乘法 FFT板子题 不行啊...跑的还是慢 应该找个机会学一学由乃dalao的fft 或者是毛爷爷的fft,跑的真是快啊... */ #include <cstdio> #include <iostream> #include <cmath> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void re

FFT多项式乘法学习笔记

??其实我不知道我是否真的理解了FFT,但是我会用FFT优化多项式乘法了QAQ.. (以下大多摘自算导 前置知识 1. 多项式 ??在一个代数域F上,关于变量x的多项式定义为形式和形式表示的函数 A(x)=∑j=0n?1ajxj,其中a0-an?1为多项式各项的系数 2. 多项式的次数界 ??若多项式有非零系数的最高次项为xk,则称k为该多项式的次数,任何严格大于k的整数都是这个多项式的次数界. 3. 多项式的表示 (1)系数表示法 ??对于一个次数界为n的多项式A(x)来说,其系数表示法可以看

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1