模拟考某题一开始由于校内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及其部分优化的更多相关文章

  1. 拆系数FFT

    学习内容:国家集训队2016论文 - 再谈快速傅里叶变换 模板题:http://uoj.ac/problem/34 1.基本介绍 对长度为L的\(A(x),B(x)\)进行DFT,可以利用 \[ \b ...

  2. 拆系数FFT(任意模数FFT)

    拆系数FFT 对于任意模数 \(mod\) 设\(m=\sqrt {mod}\) 把多项式\(A(x)\)和\(B(x)\)的系数都拆成\(a\times m+b\)的形式,时\(a, b\)都小于\ ...

  3. hdu 5730 Shell Necklace——多项式求逆+拆系数FFT

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 可以用分治FFT.但自己只写了多项式求逆. 和COGS2259几乎很像.设A(x),指数是长度,系数 ...

  4. 洛谷 4245 【模板】任意模数NTT——三模数NTT / 拆系数FFT

    题目:https://www.luogu.org/problemnew/show/P4245 三模数NTT: 大概是用3个模数分别做一遍,用中国剩余定理合并. 前两个合并起来变成一个 long lon ...

  5. 洛谷 P4245 [模板]任意模数NTT —— 三模数NTT / 拆系数FFT(MTT)

    题目:https://www.luogu.org/problemnew/show/P4245 用三模数NTT做,需要注意时间和细节: 注意各种地方要取模!传入 upt() 里面的数一定要不超过2倍 m ...

  6. hdu6088 组合数+反演+拆系数fft

    题意:两个人van石头剪子布的游戏一共n盘,假设A赢了a盘,B赢了b盘,那么得分是gcd(a,b),求得分的期望*\(3^{2*n}\) 题解:根据题意很明显有\(ans=3^{n}*\sum_{a= ...

  7. 拆系数$FFT$($4$遍$DFT$)

    #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> ...

  8. 任意模数NTT和FFT的玄学优化学习笔记

    本来一直都是写\(7\)次的\(MTT\)的--然后被\(shadowice\)巨巨调教了一通之后只好去学一下\(4\)次的了-- 简单来说就是我们现在需要处理一类模数不为\(NTT\)模数的情况 这 ...

  9. C# 拆箱与装箱及优化

    1.概念 装箱在值类型向引用类型转换时发生,在堆中分配. 拆箱在引用类型向值类型转换时发生. 2.装箱拆箱的过程 //这行语句将整型常量1赋给object类型的变量obj:众所周知常量1是值类型,值类 ...

随机推荐

  1. 理解OSI参考模型(转)

    文章转自 https://www.cnblogs.com/evablogs/p/6709707.html 一个视频网站上不小心搜到网络知识的视频,突然以前大学的没有真正接受的知识点,一下子豁然开朗,赶 ...

  2. .Net Core应用框架Util介绍(六)

    前面介绍了Util是如何封装以降低Angular应用的开发成本. 现在把关注点移到服务端,本文将介绍分层架构各构造块及基类,并对不同层次的开发人员应如何进行业务开发提供一些建议. Util分层架构介绍 ...

  3. 这段代码,c 1秒,java 9秒,c# 14秒,而python。。。

    哎,不得不说最近见得键盘侠客太多了,做程序员没两天总是喜欢上嘴唇触天,下嘴唇碰地的吹. 自己分明都没用过几门语言,就对各门语言评头论足说三道四,这么语言多好那门语言有多烂. 可能是随着时间也变得没那么 ...

  4. Dictionary实现先进先出代替Queue

    Queue删除其中一个元素比较麻烦,这是一个重码校验的类,主要处理是用Dictionary代替Queue了.目前使用下来还算稳定.代码贴出来给有缘人参考. /// <summary> // ...

  5. IDEA 创建包和类及基本操作

    创建包和类步骤如下: 1. 展开创建的工程,在源代码目录 src 上,鼠标右键,选择 new->package ,键入包名 com.itheima.demo ,点击确定. 2. 在创建好的包上, ...

  6. 用Python开发小学二年级口算自动出题程序

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 武汉光谷一小二年级要求家长每天要给小孩出口算题目,让孩子练习. 根据老师出题要求编写了Python程序 ...

  7. 数据库优化-mysql中INNODB和MYIASM引擎的区别

    Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别. 该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQ ...

  8. 【zabbix教程系列】二、zabbix特点

    一.度量收集 从任何设备,系统,应用上收集指标,收集指标的方法有: 多平台zabbix代理 SNMP and IPMI 代理 无代理监控用户服务 自定义方法 计算和聚合 用户端web监控  二.问题发 ...

  9. Python正则表达式里的单行re.S和多行re.M模式

    Python正则表达式里的单行re.S和多行re.M模式 Python 的re模块内置函数几乎都有一个flags参数,以位运算的方式将多个标志位相加.其中有两个模式:单行(re.DOTALL, 或者r ...

  10. Tensorflow 大规模数据集训练方法

    本文转自:Tensorflow]超大规模数据集解决方案:通过线程来预取 原文地址:https://blog.csdn.net/mao_xiao_feng/article/details/7399178 ...