拆系数FFT及其部分优化
模拟考某题一开始由于校内OJ太慢直接拆系数FFT跑不过
后来被神仙婊了一顿之后发现复杂度写炸了改了改随便过
模版题:任意模数NTT
三模数NTT
常数巨大,跑的极慢
拆系数FFT
原理是对于两个多项式$ P=\sum\limits_{i=0}^{n-1}P_ix^i \ \ Q=\sum\limits_{i=0}^{m-1}Q_ix^i$
直接$ FFT$计算会发现值域达到$ 10^{23}$会炸精度
设
$ A=\sum\limits_{i=0}^{n-1}(P_i>>15)x^i \ \ B=\sum\limits_{i=0}^{n-1}(P_i\&32767)x^i$
$ C=\sum\limits_{i=0}^{m-1}(Q_i>>15)x^i \ \ D=\sum\limits_{i=0}^{m-1}(Q_i\&32767)x^i$
我们只要求$ (A*C)<<30,(B*C+A*D)<<15,B*D$这三项的和即可
设一次$ DFT/IDFT$为一次操作
暴力实现需要进行$ 8$次操作
精度问题
如果用$ k$次乘法计算$ w_n^k$会损失大量精度
需要利用三角函数预处理单位根,这样可以用$ double$代替$ long \ double$
优化
参考myy的2016年集训队论文
合并$DFT$
设我们要计算$ DFT_A$和$DFT_B$
令$$ P(x)=A(x)+iB(x) \\ Q(x)=A(x)-iB(x)$$
我们只要计算一次$ DFT_P$就可以推出$ DFT_Q$
推导请参考CMXRYNP'S Blog
有
$DFT_A[i]=\frac{DFT_P[i]+DFT_Q[i]}{2}$
$DFT_B[i]=\frac{DFT_P[i]-DFT_Q[i]}{2i}$
合并$IDFT$
同理
但这里甚至不需要求$ IDFT_Q$
事实上$IDFT_P$的实部和虚部分别对应$ IDFT_A$和$IDFT_B$
这样就把$ 8$次操作减少到$4$次了
代码
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define l putchar('\n')
#define file(x)freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define block 32768
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans,p;
namespace any_module_NTT{
vector<int>R;
const double PI=acos(-1.0);
struct cp{
double x,y;
cp operator +(const cp s)const{return {x+s.x,y+s.y};}
cp operator -(const cp s)const{return {x-s.x,y-s.y};}
cp operator *(const cp s)const{return {x*s.x-y*s.y,x*s.y+y*s.x};}
}w[][<<];
void FFT(const int n,vector<cp>&A){
A.resize(n);
for(rt i=;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
for(rt i=,s=;i<n;i<<=,s++){
for(rt j=;j<n;j+=i<<){
for(rt k=;k<i;k++){
const register cp x=A[j+k],y=w[s][k]*A[i+j+k];
A[j+k]=x+y,A[i+j+k]=x-y;
}
}
}
}
vector<int>Mul(vector<int>&x,vector<int>&y){ int sz=x.size()+y.size()-,lim=;
while(lim<=sz)lim<<=;R.resize(lim);
for(rt i=;(<<i)<lim;i++)
for(rt j=;j<(<<i);j++)w[i][j]={cos(PI*j/(<<i)),sin(PI*j/(<<i))};
vector<cp>AB(lim),CD(lim),AC(lim),BC(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
for(rt i=;i<x.size();i++)AB[i].x=((ll)x[i])&,AB[i].y=((ll)x[i])>>;
for(rt i=;i<y.size();i++)CD[i].x=((ll)y[i])&,CD[i].y=((ll)y[i])>>;
FFT(lim,AB);FFT(lim,CD);
for(rt i=;i<lim;i++){
static cp na,nb,nc,nd;const int pl=(lim-)&(lim-i);
na=AB[i]+(cp){AB[pl].x,-AB[pl].y},nb=AB[i]-(cp){AB[pl].x,-AB[pl].y};
nc=CD[i]+(cp){CD[pl].x,-CD[pl].y},nd=CD[i]-(cp){CD[pl].x,-CD[pl].y};
const cp v1={0.5,},v2={,-0.5};
na=na*v1;nb=nb*v2;nc=nc*v1;nd=nd*v2;
AC[pl]=na*nc+na*nd*(cp){,};
BC[pl]=nb*nc+nb*nd*(cp){,};
}
FFT(lim,AC);FFT(lim,BC);
vector<int>ans(sz);
for(rt i=;i<sz;i++){
ll v1=AC[i].x/lim+0.5,v2=AC[i].y/lim+BC[i].x/lim+0.5,v3=BC[i].y/lim+0.5;
ans[i]=(ll)((v3%p<<)+(v2%p<<)+v1)%p;
}
return ans;
}
}
using namespace any_module_NTT;
vector<int>A,B;
int main(){
n=read();A.resize(n+);m=read();B.resize(m+);p=read();
for(rt i=;i<=n;i++)A[i]=read();for(rt i=;i<=m;i++)B[i]=read();
A=Mul(A,B);
for(rt i=;i<=n+m;i++)write((A[i]+p)%p),putchar(' ');
return ;
}
拆系数FFT及其部分优化的更多相关文章
- 拆系数FFT
学习内容:国家集训队2016论文 - 再谈快速傅里叶变换 模板题:http://uoj.ac/problem/34 1.基本介绍 对长度为L的\(A(x),B(x)\)进行DFT,可以利用 \[ \b ...
- 拆系数FFT(任意模数FFT)
拆系数FFT 对于任意模数 \(mod\) 设\(m=\sqrt {mod}\) 把多项式\(A(x)\)和\(B(x)\)的系数都拆成\(a\times m+b\)的形式,时\(a, b\)都小于\ ...
- hdu 5730 Shell Necklace——多项式求逆+拆系数FFT
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 可以用分治FFT.但自己只写了多项式求逆. 和COGS2259几乎很像.设A(x),指数是长度,系数 ...
- 洛谷 4245 【模板】任意模数NTT——三模数NTT / 拆系数FFT
题目:https://www.luogu.org/problemnew/show/P4245 三模数NTT: 大概是用3个模数分别做一遍,用中国剩余定理合并. 前两个合并起来变成一个 long lon ...
- 洛谷 P4245 [模板]任意模数NTT —— 三模数NTT / 拆系数FFT(MTT)
题目:https://www.luogu.org/problemnew/show/P4245 用三模数NTT做,需要注意时间和细节: 注意各种地方要取模!传入 upt() 里面的数一定要不超过2倍 m ...
- hdu6088 组合数+反演+拆系数fft
题意:两个人van石头剪子布的游戏一共n盘,假设A赢了a盘,B赢了b盘,那么得分是gcd(a,b),求得分的期望*\(3^{2*n}\) 题解:根据题意很明显有\(ans=3^{n}*\sum_{a= ...
- 拆系数$FFT$($4$遍$DFT$)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> ...
- 任意模数NTT和FFT的玄学优化学习笔记
本来一直都是写\(7\)次的\(MTT\)的--然后被\(shadowice\)巨巨调教了一通之后只好去学一下\(4\)次的了-- 简单来说就是我们现在需要处理一类模数不为\(NTT\)模数的情况 这 ...
- C# 拆箱与装箱及优化
1.概念 装箱在值类型向引用类型转换时发生,在堆中分配. 拆箱在引用类型向值类型转换时发生. 2.装箱拆箱的过程 //这行语句将整型常量1赋给object类型的变量obj:众所周知常量1是值类型,值类 ...
随机推荐
- MySQL之ORM框架SQLAlchemy
一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...
- macos 下usb键盘问题.
Mac 与PC键盘的对比及快捷键(黑苹果) https://www.jianshu.com/p/240f31f6f81a 剩下的就是 系统偏好设置 - 键盘 - 修饰键 - USB键盘(目标键盘) 把 ...
- vue.js 跳转同一页面,传不同值,组件监听路由
watch: { '$route' () { this.type = this.$route.params.type this.loadData() } },
- C. Songs Compression(简单贪心)
水题 #include<iostream> #include<algorithm> using namespace std; #define LL long long ; st ...
- 正益工作能担起PaaS+SaaS的未来探索吗?
没有竞争,行业没有未来.不参与竞争,企业没有未来.中国企业的类型纷繁复杂,也决定了企业的多样化需求.云计算和移动化的双重叠加,企业管理需要重新梳理,企业业务创新日益频繁,个性化需求日益突出,软件服务商 ...
- python3 二分法查找
'''二分法查找有序列表掐头去尾取中间查找列表中xx在不在列表中,在,则返回索引值'''# lst = [1, 4, 6, 8, 9, 21, 23, 26, 35, 48, 49, 54, 67, ...
- zsh : command not found pip3 的解决方案
问题描述 在 zsh 中执行 pip xxx ,出现错误 zsh: command not found: pip3 . 当然我很确定自己是有安装 pip3 的,应该是应该切换了shell,导致环境变量 ...
- Flask中使用数据库连接池 DBUtils ——(4)
DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程 ...
- DAY17、常用模块
一.time模块 1.时间戳(timestamp):time.time() #可以作为数据的唯一标识 是相对于1970-1-1-0:0:0时间插值 2.延迟线程的运行:time.sleep ...
- Delphi Create(nil), Create(self), Create(Application)的区别
最近的项目中经常在程序中动态创建控件,势必用到Create. 但是随之而来的问题就是动态创建的控件是否可以正确的释放内存? 以及 Create(nil), Create(self), Create(A ...