FFT 的一些技巧
三次变两次 FFT
我们发现:
\]
也就是说,我们把 \(F(x)\) 作为实部,\(G(x)\) 作为虚部,那么它的平方的虚部的 \(1/2\) 就是 \(F(x)G(x)\)
可惜精度比较低。
四次 FFT 求任意模数多项式乘法
假设我们要求 \(M(x)\times N(x)\pmod{p}\),因为如果我们直接 FFT 就会爆 double ,所以我们可以把 \(M(x)\) 拆成 \(kA(x)+B(x)\),\(N(x)\) 拆成 \(kC(x)+D(x)\),其中 \(k\approx \sqrt{p}\),那么,你的值域就大约变为 \(p\times n\) 的了,但是你就需要 \(7\) 次 FFT 了。
我们假设有 \(Q(x)=A(x)+iB(x),E(x)=C(x)+iD(x)\),设 \(q(x_1)\) 表示 \(Q(x)\) 在 \(x_1\) 的取值,\(A_j\) 表示 \(A(x)\) 第 \(j\) 项系数,那么我们就有:
\]
\]
\]
\]
\]
我们假设 \(q(x).r\) 表示它的实部,\(q(x).f\) 表示它的虚部,那么我们就可以得到:
\]
\]
然后,我们求出 \(A(x)E(x)\) 和 \(B(x)E(x)\),我们就可以得到 \(A(x)C(x),A(x)D(x),B(x)C(x),B(x)D(x)\),然后算就好了。
暂时没有懂 \(3.5\) 次 FFT 的做法,所以不写了。
Code
#include <bits/stdc++.h>
using namespace std;
#define double long double
#define Int register int
#define MAXN 270005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
struct Complex{
double x,y;
Complex(){}
Complex (double _x,double _y){x = _x,y = _y;}
Complex operator / (const double &p)const{return Complex{x / p,y / p};}
Complex operator + (const Complex &p)const{return Complex{x + p.x,y + p.y};}
Complex operator - (const Complex &p)const{return Complex{x - p.x,y - p.y};}
Complex operator * (const Complex &p)const{return Complex{x * p.x - y * p.y,x * p.y + p.x * y};}
};
#define pi (double)acos(-1)
int l,lim,rev[MAXN];
void fft (Complex *a,int type){
for (Int i = 0;i < lim;++ i) if (i < rev[i]) swap (a[i],a[rev[i]]);
for (Int i = 1;i < lim;i <<= 1){
Complex Wn(cos(pi / i),type * sin(pi / i));
for (Int j = 0,r = i << 1;j < lim;j += r){
Complex w(1,0);
for (Int k = 0;k < i;++ k,w = w * Wn){
Complex x = a[j + k],y = w * a[i + j + k];
a[j + k] = x + y,a[i + j + k] = x - y;
}
}
}
if (type == -1) for (Int i = 0;i < lim;++ i) a[i] = a[i] / lim;
}
int n,m,mod,a[MAXN],b[MAXN],ans[MAXN];
Complex Q[MAXN],E[MAXN],C[MAXN],D[MAXN];
#define ll long long
signed main(){
read (n,m,mod),lim = 1;
while (lim < n + m) lim <<= 1,++ l;
for (Int i = 0;i < lim;++ i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << l - 1);int up = (1 << 15) - 1;
for (Int i = 0;i <= n;++ i) read (a[i]),Q[i] = Complex (a[i] >> 15,a[i] & up);
for (Int i = 0;i <= m;++ i) read (b[i]),E[i] = Complex (b[i] >> 15,b[i] & up);
fft (Q,1),fft (E,1);
for (Int i = 0;i < lim;++ i){
int re = (lim - 1) & (lim - i);
C[i] = Complex((Q[i].x + Q[re].x) / 2,(Q[i].y - Q[re].y) / 2) * E[i];
D[i] = Complex((Q[re].y + Q[i].y) / 2,(Q[re].x - Q[i].x) / 2) * E[i];
}
fft (C,-1),fft (D,-1);
for (Int i = 0;i < lim;++ i){
ll v1 = (ll)(C[i].x + 0.5) % mod,v2 = (ll)(C[i].y + D[i].x + 0.5) % mod,v3 = (ll)(D[i].y + 0.5) % mod;
ans[i] = ((v1 << 30) + (v2 << 15) + v3) % mod;
}
for (Int i = 0;i <= n + m;++ i) write ((ans[i] % mod + mod) % mod),putchar (' ');
putchar ('\n');
return 0;
}
FFT 的一些技巧的更多相关文章
- [Algorithm] Polynomial and FFT
排序:nlogn 二分查找:logn <-- 利用单调性,查n次,每次logn Multiply the following pairs of polynomials using at most ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- 快速傅里叶变换(FFT)学习笔记(其一)
再探快速傅里叶变换(FFT)学习笔记(其一) 目录 再探快速傅里叶变换(FFT)学习笔记(其一) 写在前面 为什么写这篇博客 一些约定 前置知识 多项式卷积 多项式的系数表达式和点值表达式 单位根及其 ...
- 快速傅里叶变换(FFT)学习笔记(其二)(NTT)
再探快速傅里叶变换(FFT)学习笔记(其二)(NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其二)(NTT) 写在前面 一些约定 前置知识 同余类和剩余系 欧拉定理 阶 原根 求原根 NTT ...
- Codeforces 986D - Perfect Encoding(FFT+爪巴卡常题)
题面传送门 题意:给出 \(n\),构造出序列 \(b_1,b_2,\dots,b_m\) 使得 \(\prod\limits_{i=1}^mb_i\geq n\),求 \(\sum\limits_{ ...
- HNOI2018题解
在此处输入标题 标签(空格分隔): 未分类 重做了一遍,本来以为很快的,结果搞了一天... 寻宝游戏 可以发现只有\(\&0\)和\(|1\)会对答案有影响 那么对于每一位,我们只要知道最后一 ...
- sgu
dp第几朵花放第几瓶 104 数论 能不能除3:105 106(ex_gcd引入t求范围交) 107(大数乘的FFT) 开空间技巧108 棋盘黑白格消除109(组合数学) java平方根 ...
- 打FFT时中发现的卡常技巧
题目:洛谷P1919 A*B Problem 加强版 我的代码完全借鉴boshi,然而他380ms我880ms...于是我通过彻底的卡(chao)常(dai)数(ma)成功优化到了380ms,都是改了 ...
- 算法系列:FFT 002
转载自http://blog.jobbole.com/58246/ 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.没有正规计算机科学课程背景 ...
随机推荐
- Redis笔记(一)
redis:1.什么是缓存? mybatis一级缓存和二级缓存 mybatis的一级缓存存在哪? SqlSession,就不会再走数据库 什么情况下一级缓存会失效? 当被更新,删除的时候sqlsess ...
- Hutool中那些常用的工具类和方法
Hutool中那些常用的工具类和方法 Hutool是一个Java工具包,它帮助我们简化每一行代码,避免重复造轮子.如果你有需要用到某些工具方法的时候,不妨在Hutool里面找找,可能就有.本文将对Hu ...
- 安全强化机制——SELinux
1.基本 SELINUX 安全性概念 SELINUX(Security Enhanced Linux),意思是安全增强型Linux, 是可保护你系统安全性的额外机制 在某种程度上 , 它可以被看作是与 ...
- VS Code 搭建stm32开发环境
MCU免费开发环境 一般芯片厂家会提供各种开发IDE方案,通常其中就包括其自家的集成IDE,如: 意法半导体 STM32CubeIDE NXP Codewarrior TI CCS 另外也可以用ecl ...
- app自动化定位:UIautomation的用法
UIautomation定位的优点: 速度比xpath定位快,UIautomation是Android的工作引擎 缺点: 没有idea提示 UIautomation使用方法: AndroidDrive ...
- ActiveMQ和消息中间件概念
一.概念
- POJ1804——Brainman(水题)
解题思路: 一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数 直接求逆序数 把S[i]和s[i+1~n]的元素逐个比较,如果s[i] > s[k] (k∈[i ...
- 3.15学习总结(Python爬取网站数据并存入数据库)
在官网上下载了Python和PyCharm,并在网上简单的学习了爬虫的相关知识. 结对开发的第一阶段要求: 网上爬取最新疫情数据,并存入到MySql数据库中 在可视化显示数据详细信息 项目代码: im ...
- POJ 2509 Peter's smokes(Peter的香烟)
POJ 2509 Peter的香烟 描述 Peter抽烟.他抽烟一个个地抽着烟头.从 k (k>1) 个烟头中,他可以抽一根新烟.彼得可以抽几支烟? 输入 输入是一系列行.每行包含两个给出n和k ...
- Django学习day10随堂笔记
每日测验 """ 今日考题 1.默写ajax基本语法,及提交json数据和文件都需要添加哪些额外参数 2.什么是序列化,截止目前为止你所接触过的序列化有哪些 3.批量插入 ...