参考资料

picks

miskcoo

menci

胡小兔

unname

自为风月马前卒

上面是FFT的,学完了就来看NTT

原根

例题:luogu3803

fft优化后模板

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, m, lim=1, rev[2100005];
const double PI=acos(-1.0);
struct Complex{
double x, y;
Complex(double xx=0.0, double yy=0.0){
x = xx;
y = yy;
}
Complex operator+(const Complex &u)const{
return Complex(x+u.x, y+u.y);
}
Complex operator-(const Complex &u)const{
return Complex(x-u.x, y-u.y);
}
Complex operator*(const Complex &u)const{
return Complex(x*u.x-y*u.y, x*u.y+y*u.x);
}
}a[2100005], b[2100005];
template<typename T> void rn(T &x){
x = 0;
char ch=getchar();
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0' && ch<='9'){
x = x * 10 + ch - '0';
ch = getchar();
}
}
void fft(Complex a[], int opt){
for(int i=0; i<lim; i++)
if(i<rev[i])
swap(a[i], a[rev[i]]);
for(int i=2; i<=lim; i<<=1){
int tmp=i>>1;
Complex wn=Complex(cos(PI*2.0/i), opt*sin(PI*2.0/i));
for(int j=0; j<lim; j+=i){
Complex w=Complex(1.0, 0.0);
for(int k=0; k<tmp; k++){
Complex tmp1=a[j+k], tmp2=w*a[j+k+tmp];
a[j+k] = tmp1 + tmp2;
a[j+k+tmp] = tmp1 - tmp2;
w = w * wn;
}
}
}
if(opt==-1)
for(int i=0; i<lim; i++)
a[i].x /= lim;
}
int main(){
cin>>n>>m;
for(int i=0; i<=n; i++) rn(a[i].x);
for(int i=0; i<=m; i++) rn(b[i].x);
int tmpcnt=0;
while(lim<=n+m) lim <<= 1, tmpcnt++;
for(int i=0; i<lim; i++)
rev[i] = (rev[i>>1]>>1) | ((i&1)<<(tmpcnt-1));
fft(a, 1);
fft(b, 1);
for(int i=0; i<lim; i++)
a[i] = a[i] * b[i];
fft(a, -1);
for(int i=0; i<=n+m; i++)
printf("%d ", (int)(a[i].x+0.5));
printf("\n");
return 0;
}

NTT

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, a[2100005], b[2100005], lim=1, limcnt, rev[2100005];
const int mod=998244353, gg=3, gi=332748118;
void rn(int &x){
char ch=getchar();
x = 0;
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0' && ch<='9'){
x = x * 10 + ch - '0';
ch = getchar();
}
}
int ksm(int a, int b){
int re=1;
while(b){
if(b&1) re = (ll)re * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return re;
}
void ntt(int a[], int opt){
for(int i=0; i<lim; i++)
if(i<rev[i])
swap(a[i], a[rev[i]]);
for(int i=2; i<=lim; i<<=1){
int tmp=i>>1, wn=ksm(opt==1?gg:gi, (mod-1)/i);
for(int j=0; j<lim; j+=i){
int w=1;
for(int k=0; k<tmp; k++){
int tmp1=a[j+k], tmp2=(ll)w*a[j+k+tmp]%mod;
a[j+k] = (tmp1 + tmp2) % mod;
a[j+k+tmp] = (tmp1 - tmp2 + mod) % mod;
w = (ll)w * wn % mod;
}
}
}
if(opt==-1){
int inv=ksm(lim, mod-2);
for(int i=0; i<lim; i++)
a[i] = (ll)a[i] * inv % mod;
}
}
int main(){
cin>>n>>m;
for(int i=0; i<=n; i++) rn(a[i]);
for(int i=0; i<=m; i++) rn(b[i]);
while(lim<=n+m) lim <<= 1, limcnt++;
for(int i=0; i<lim; i++)
rev[i] = (rev[i>>1]>>1) | ((i&1)<<(limcnt-1));
ntt(a, 1);
ntt(b, 1);
for(int i=0; i<lim; i++)
a[i] = (ll)a[i] * b[i] % mod;
ntt(a, -1);
for(int i=0; i<=n+m; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}

递归版裸fft没什么优化

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, m;
const double PI=acos(-1.0);
struct Complex{
double x, y;
Complex(double xx=0.0, double yy=0.0){
x = xx;
y = yy;
}
Complex operator+(const Complex &u)const{
return Complex(x+u.x, y+u.y);
}
Complex operator-(const Complex &u)const{
return Complex(x-u.x, y-u.y);
}
Complex operator*(const Complex &u)const{
return Complex(x*u.x-y*u.y, x*u.y+y*u.x);
}
}a[4000005], b[4000005], buf[4000005];
void fft(Complex a[], int lim, int opt){
if(lim==1) return ;
int tmp=lim/2;
for(int i=0; i<tmp; i++){
buf[i] = a[2*i];
buf[i+tmp] = a[2*i+1];
}
for(int i=0; i<lim; i++)
a[i] = buf[i];
fft(a, tmp, opt);
fft(a+tmp, tmp, opt);
Complex wn=Complex(cos(PI*2.0/lim), opt*sin(PI*2.0/lim)), w=Complex(1.0, 0.0);
for(int i=0; i<tmp; i++){
buf[i] = a[i] + w * a[i+tmp];
buf[i+tmp] = a[i] - w * a[i+tmp];
w = w * wn;
}
for(int i=0; i<lim; i++)
a[i] = buf[i];
}
int main(){
cin>>n>>m;
for(int i=0; i<=n; i++) scanf("%lf", &a[i].x);
for(int i=0; i<=m; i++) scanf("%lf", &b[i].x);
int lim=1;
while(lim<=n+m) lim <<= 1;
fft(a, lim, 1);
fft(b, lim, 1);
for(int i=0; i<=lim; i++)
a[i] = a[i] * b[i];
fft(a, lim, -1);
for(int i=0; i<=n+m; i++)
printf("%d ", (int)(a[i].x/lim+0.5));
printf("\n");
return 0;
}

FFT、NTT学习笔记的更多相关文章

  1. FFT&NTT学习笔记

    具体原理就不讲了qwq,毕竟证明我也不太懂 FFT(快速傅立叶变换)&NTT(快速数论变换) FFT //求多项式乘积 //要求多项式A和多项式B的积多项式C //具体操作就是 //DFT(A ...

  2. FFT/NTT 学习笔记

    0. 前置芝士 基础群论 复数 \(\mathbb C = \mathbb R[x^2+1]\) 则有 \(i^2+1=(-i)^2+1=0\),\(i \in \mathbb C - \mathbb ...

  3. FFT和NTT学习笔记_基础

    FFT和NTT学习笔记 算法导论 参考(贺) http://picks.logdown.com/posts/177631-fast-fourier-transform https://blog.csd ...

  4. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ

    第三波,走起~~ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ 单位根反演 今天打多校时 1002 被卡科技了 ...

  5. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ

    众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...

  6. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ

    因为垃圾电脑太卡了就重开了一个... 前传:多项式Ⅰ u1s1 我预感还会有Ⅲ 多项式基础操作: 例题: 26. CF438E The Child and Binary Tree 感觉这题作为第一题还 ...

  7. 快速傅里叶变换(FFT)学习笔记(未完待续)

    目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...

  8. NTT学习笔记

    和\(FFT\)相对应的,把单位根换成了原根,把共轭复数换成了原根的逆元,最后输出的时候记得乘以原\(N\)的逆元即可. #include <bits/stdc++.h> using na ...

  9. NTT 学习笔记

    引入 \(\tt NTT\) 和 \(\tt FFT\) 有什么不一样呢? 就是 \(\tt NTT\) 是可以用来取模的,而且没有复数带来的精度误差. 最最重要的是据说 \(\tt NTT\) 常数 ...

随机推荐

  1. 浅析HTML的元素类型及其转换

    大家都知道html是由标签元素组成的,在了解元素的类型转换之前,让我们先来了解一下html的元素类型. 一.html元素类型分为两种:块级元素和内联元素,内联元素又被称为行内元素.  常见的块级元素有 ...

  2. android动画ppt整理

    案例

  3. The Mythical Man-Month

    大家所熟知的Windows XP操作系统,源代码行数已经达到40百万行.为了连接用户和计算机底层硬件,庞大操作系统这一层太过于复杂,没有一个人能完全理解它如此数量的所有代码,而多人的合作开发又需要它被 ...

  4. github入门之更改提交操作--6

    1.回溯历史版本 1.1.回溯到创建feature-A分支前 1.1.1.要让仓库的HEAD.暂存区.当前工作树回溯到指定状态,需要用到提供目标时间点的哈希值 1.1.2.回溯至未创建feature- ...

  5. Eclipse IDE配置PHP开发、调试环境

    前言 使用java语言开发的朋友想必对Eclipse开发工具已经不陌生了,那么Eclipse作为java主流的开发工具,是否能够开发PHP项目呢?答案如你所想,肯定是可以的!以下就是该IDE下如何配置 ...

  6. Windows Azure 配置Active Directory 主机(1)

    现在越来越多企业将自己业务系统迁移云端,方便公司日常运维管理.这篇文章将简单介绍一下,从 Windows Azure 虚拟网络上的虚拟机 (VM) 中的 Corp Active Directory 林 ...

  7. python+selenium之验证码的处理

    对于web应用来说,大部分的系统在用户登录时都要求用户输入验证码.验证码的类型很多,有字母数字的,有汉字的.甚至还有需要用户输入一道算术题的答案的.对于系统来说,使用验证码可以有效地防止采用机器猜测方 ...

  8. python+selenium之多表单切换

    在Web应用中经常会遇到fram/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于fram/iframe表单内嵌套页面上的元素无法直接定位.这是需要通过swit ...

  9. Tomcat控制台乱码问题

    乱码效果图 解决办法 1.修改cmd的编码格式 快捷键win+R打开运行程序,输入regedit打开注册表,找到以下路劲并且修改. [HKEY_LOCAL_MACHINE\SOFTWARE\Micro ...

  10. div高度不能自适应(子级使用float浮动,父级div高度不能自适应)

    1.问题截图: 2.问题描述: 由于地址.公司名长度的不定性,所以每一条地址所在的父级div高度不定,但是需要设置一个最小的高度min-height:48px;但是当内容增加的时候,父级div高度却不 ...