任意模数FFT

这是一个神奇的魔法,但是和往常一样,在这之前,先

\(\texttt{orz}\ \color{orange}{\texttt{matthew99}}\)

问题描述

给定 2 个多项式 \(F(x), G(x)\) ,请求出 \(F(x) * G(x)\)。

系数对 p 取模,\(2 \le p \le 10^9+9\)

拆系数FFT

我们考虑令\(M\)为\(\sqrt{p}\),那么我们可以将原本的多项式拆成4个。

\(F(x)=A(x)*M+B(x)\)

\(G(X)=C(X)*M+D(x)\)

然后\(A\),\(B\),\(C\),\(D\)随便乘一下就可以求出答案。

这样需要的\(FFT\)次数为7次。

合并FFT

我们思考一下有没有什么优化的方法呢?

令\(P(x)=A(x)+iB(x)\),\(Q(x)=A(x)-iB(x)\)

\(F_p[k]\)和\(F_q[k]\)分别表示\(P\)和\(Q\)做了\(DFT\)后的\(k\)项系数。

推一推式子可以发现\(F_q[k]=conj(F_p[2L-k])\)。

那么我们只需要1遍\(DFT\)就可以求出这两个东西。

此时我们把模意义下的多项式乘法转换成了复数意义下的多项式乘法,就只需要按照\(FFT\)的过程实现。

把实部与虚部合并即可。

注意此时\(FFT\)的精度十分爆炸,所以用\(long\ double\)并预处理单位根比较好。

/*
mail: mleautomaton@foxmail.com
author: MLEAutoMaton
This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
{
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=1000010;const long double Pi=acos(-1.0);
int n,m,f[N],g[N],Mod;
struct node
{
long double x,y;
node operator+(const node &b)const{return (node){x+b.x,y+b.y};}
node operator-(const node &b)const{return (node){x-b.x,y-b.y};}
node operator*(const node &b)const{return (node){x*b.x-y*b.y,x*b.y+y*b.x};}
};
int r[N],limit,ans[N];
void fft(node *a,int opt)
{
for(int i=0;i<limit;i++)
if(i<r[i])swap(a[i],a[r[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
node Root=(node){cos(Pi/mid),opt*sin(Pi/mid)};
for(int R=mid<<1,i=0;i<limit;i+=R)
{
node W=(node){1,0};
for(int j=0;j<mid;j++,W=W*Root)
{
node X=a[i+j],Y=W*a[mid+i+j];
a[i+j]=X+Y;a[mid+i+j]=X-Y;
}
}
}
}
node a[N],b[N],c[N],d[N];
void mtt()
{
int LIM=(1<<15)-1;
for(int i=0;i<=n;i++)f[i]=(f[i]+Mod)%Mod;for(int i=0;i<=m;i++)g[i]=(g[i]+Mod)%Mod;
for(int i=0;i<=n;i++)a[i]=(node){f[i]&LIM,f[i]>>15};
for(int i=0;i<=m;i++)b[i]=(node){g[i]&LIM,g[i]>>15};
fft(a,1);fft(b,1);
for(int i=0;i<limit;i++)c[i]=a[i],d[i]=b[i];
for(int i=0;i<limit;i++)
{
int j=(limit-i)&(limit-1);
a[i]=(node){0.5*(c[i].x+c[j].x),0.5*(c[i].y-c[j].y)}*d[i];
b[i]=(node){0.5*(c[i].y+c[j].y),0.5*(c[j].x-c[i].x)}*d[i];
}
fft(a,-1);fft(b,-1);
for(int i=0;i<limit;i++)
{
ll ia,ib,ic,id;
ia=(ll)(a[i].x/limit+0.5)%Mod;
ib=(ll)(a[i].y/limit+0.5)%Mod;
ic=(ll)(b[i].x/limit+0.5)%Mod;
id=(ll)(b[i].y/limit+0.5)%Mod;
ans[i]=((ia%Mod+((ib+ic)%Mod<<15))%Mod+(id%Mod<<30))%Mod;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
#endif
n=gi();m=gi();Mod=gi();
for(int i=0;i<=n;i++)f[i]=gi();for(int i=0;i<=m;i++)g[i]=gi();
limit=1;int l=0;
while(limit<=(n+m))limit<<=1,l++;
for(int i=0;i<limit;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
mtt();
for(int i=0;i<=n+m;i++)printf("%d ",(ans[i]+Mod)%Mod);
return 0;
}

题目

任意模数NTT

Shell Necklace

任意模数FFT的更多相关文章

  1. 【集训队作业2018】取名字太难了 任意模数FFT

    题目大意 求多项式 \(\prod_{i=1}^n(x+i)\) 的系数在模 \(p\) 意义下的分布,对 \(998244353\) 取模. \(p\) 为质数. \(n\leq {10}^{18} ...

  2. 51nod 1172 Partial Sums V2 卡精度的任意模数FFT

    卡精度的任意模数fft模板题……这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数fft模板题.然后我就去网上抄了一下板子……我打的是最土的任意模数f ...

  3. 51NOD 1258 序列求和 V4 [任意模数fft 多项式求逆元 伯努利数]

    1258 序列求和 V4 题意:求\(S_m(n) = \sum_{i=1}^n i^m \mod 10^9+7\),多组数据,\(T \le 500, n \le 10^{18}, k \le 50 ...

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

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

  5. hdu 4656 Evaluation [任意模数fft trick]

    hdu 4656 Evaluation 题意:给出\(n,b,c,d,f(x) = \sum_{i=1}^{n-1} a_ix^i\),求\(f(b\cdot c^{2k}+d):0\le k < ...

  6. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  7. 任意模数NTT

    任意模数\(NTT\) 众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + r\)且\(2^k \ge n\) 比较常用的有\(998244353,1004 ...

  8. 【模板】任意模数NTT

    题目描述: luogu 题解: 用$fft$水过(什么$ntt$我不知道). 众所周知,$fft$精度低,$ntt$处理范围小. 所以就有了任意模数ntt神奇$fft$! 意思是这样的.比如我要算$F ...

  9. MTT:任意模数NTT

    MTT:任意模数NTT 概述 有时我们用FFT处理的数据很大,而模数可以分解为\(a\cdot 2^k+1\)的形式.次数用FFT精度不够,用NTT又找不到足够大的模数,于是MTT就应运而生了. MT ...

随机推荐

  1. 易百教程人工智能python修正-人工智能数据准备-标记数据

    我们已经知道,某种格式的数据对于机器学习算法是必需的. 另一个重要的要求是,在将数据作为机器学习算法的输入发送之前,必须正确标记数据. 例如,如果所说的分类,那么数据上会有很多标记. 这些标记以文字, ...

  2. iOS - 第三方库总结篇

    Swift版本点击这里 欢迎加入QQ群交流: 594119878 About A curated list of iOS objective-C ecosystem. How to Use Simpl ...

  3. python3基础之“函数(2)”

    1.def:定义一个函数 def f(x): return x+1 #返回函数值 a=f(2) print(a) >>3 def even_odd(x): if x%2==0: " ...

  4. 【方法】list<?> 两个list集合 查找不同元素,求差值

    //方法1 //自己声明list//思路,从list1中删除list2中相同的元素//使用循环遍历对比的方式删除//list1包含list2,list1多与list2//结束得出list1为不相同元素 ...

  5. 【layui】layer.photos 相册层动态生成Img 中出现的问题的解决方案

    layui版本:2.5.5 参照文档:https://www.jianshu.com/p/c594811fa882 他的3.8的解决方案有一些调整因为发现他的解决方式有些繁琐而最新的2.5.5版本中有 ...

  6. HBuilderX打包成安卓或苹果app之后的调试问题,避免每次都要打包

    一.使用VScode安装 Live Server插件 二.使用:安装成功后---->>新建一个index.html 写入内容如下图所示 注:href地址是你在电脑上启动该项目的访问地址(此 ...

  7. c#生成高清字体图片

    Graphics g = Graphics.FromImage(image); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Hig ...

  8. adb命令获取app布局文件xml

    adb shell /system/bin/uiautomator dump --compressed /data/local/tmp/uidump.xml adb pull /data/local/ ...

  9. iview 标题内边距过大; 调整iview 单元格内边距、行高;

    1css代码: /*调整table cell间隔和行高*/ .ivu-table-cell { padding-left: 1px; padding-right: 1px; } .ivu-table- ...

  10. Flask之DButils

    一.简介 在使用pymysql时遇到一些问题,就是当用户访问过多时,pymysql它同一时间只能处理一个线程.大大的降低了效率,对此我们基于DBUtils实现数据链接池. 二.安装与使用 创建数据库连 ...