讲解:http://www.cnblogs.com/poorpool/p/8760748.html

递归版FFT

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAXN = 4000005;
const double PI = acos(-1);
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return rv * fh;
}
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[MAXN], b[MAXN], buf[MAXN];
int n, m;
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[i * 2];
buf[tmp + i] = a[i * 2 + 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() {
n = init(); m = init();
for(int i = 0; i <= n; i++) a[i].x = init();
for(int i = 0; i <= m; i++) b[i].x = init();
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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 4000005;
const double PI = acos(-1);
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return rv * fh;
}
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[MAXN], b[MAXN], buf[MAXN];
int n, m, rev[MAXN], lim, limcnt;
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 mid = 1; mid < lim; mid <<= 1) {
Complex wn = Complex(cos(PI / mid), opt * sin(PI / mid));
for(int R = mid << 1, j = 0; j < lim; j += R) {
Complex w = Complex(1.0, 0.0);
for(int k = 0; k < mid; k++) {
Complex x = a[j + k], y = w * a[j + mid + k];
a[j + k] = x + y;
a[j + mid + k] = x - y;
w = w * wn;
}
}
}
}
int main() {
n = init(); m = init();
for(int i = 0; i <= n; i++) a[i].x = init();
for(int i = 0; i <= m; i++) b[i].x = init();
lim = 1;
while(lim <= n + m) {lim <<= 1; limcnt++;}
for(int i = 0; i <= lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (limcnt - 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 / lim + 0.5));
}
return 0;
}

NTT

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int MAXN = 4000005, MOD = 998244353, gg = 3, gi = 332748118;
ll init() {
ll rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return fh * rv;
}
ll lim = 1, limcnt, rev[MAXN], n, m, a[MAXN], b[MAXN];
ll ksm(ll a, ll k) {
ll ans = 1;
while(k) {
if(k & 1ll) {
(ans *= a) %= MOD;
}
(a *= a) %= MOD;
k >>= 1;
}
return ans;
}
void ntt(ll a[], int opt) {
for(int i = 0; i <= lim; i++) {
if(i < rev[i]) swap(a[i], a[rev[i]]);
}
for(int mid = 1; mid < lim; mid <<= 1) {
ll wn = ksm(opt == 1 ? gg : gi, (MOD - 1) / (mid << 1));
for(int R = mid << 1, j = 0; j < lim; j += R) {
ll w = 1;
for(int k = 0; k < mid; k++) {
ll x = a[j + k], y = w * a[j + mid + k] % MOD;
a[j + k] = (x + y) % MOD;
a[j + mid + k] = (x - y + MOD) % MOD;
(w *= wn) %= MOD;
}
}
}
if(opt == -1) {
ll inv = ksm(lim, MOD - 2);
for(int i = 0; i <= lim; i++) {
(a[i] *= inv) %= MOD;
}
}
}
int main() {
n = init(); m = init();
for(int i = 0; i <= n; i++) {
a[i] = init();
}
for(int i = 0; i <= m; i++) b[i] = init();
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] = a[i] * b[i]) %= MOD;
ntt(a, -1);
for(int i = 0; i <= n + m; i++) {
printf("%lld ", a[i]);
}
printf("\n");
return 0;
}

FFT与NTT的更多相关文章

  1. 多项式乘法,FFT与NTT

    多项式: 多项式?不会 多项式加法: 同类项系数相加: 多项式乘法: A*B=C $A=a_0x^0+a_1x^1+a_2x^2+...+a_ix^i+...+a_{n-1}x^{n-1}$ $B=b ...

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

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

  3. fft,ntt总结

    一个套路:把式子推成卷积形式,然后用fft或ntt优化求解过程. fft的扩展性不强,不可以在fft函数里多加骚操作--DeepinC T1:多项式乘法 板子题 T2:快速傅立叶之二 另一个板子,小技 ...

  4. 多项式fft、ntt、fwt 总结

    做了四五天的专题,但是并没有刷下多少题.可能一开始就对多项式这块十分困扰,很多细节理解不深. 最简单的形式就是直接两个多项式相乘,也就是多项式卷积,式子是$N^2$的.多项式算法的过程就是把卷积做一种 ...

  5. FFT与NTT专题

    先不管旋转操作,考虑化简这个差异值 $$begin{aligned}sum_{i=1}^n(x_i-y_i-c)^2&=sum_{i=1}^n(x_i-y_i)^2+nc^2-2csum_{i ...

  6. 卷积FFT、NTT、FWT

    先简短几句话说说FFT.... 多项式可用系数和点值表示,n个点可确定一个次数小于n的多项式. 多项式乘积为 f(x)*g(x),显然若已知f(x), g(x)的点值,O(n)可求得多项式乘积的点值. ...

  7. 多项式的基本运算(FFT和NTT)总结

    设参与运算的多项式最高次数是n,那么多项式的加法,减法显然可以在O(n)时间内计算. 所以我们关心的是两个多项式的乘积.朴素的方法需要O(n^2)时间,并不够优秀. 考虑优化. 多项式乘积 方案一:分 ...

  8. 浅谈FFT、NTT和MTT

    前言 \(\text{FFT}\)(快速傅里叶变换)是 \(O(n\log n)\) 解决多项式乘法的一个算法,\(\text{NTT}\)(快速数论变换)则是在模域下的,而 \(\text{MTT} ...

  9. hdu 1402(FFT乘法 || NTT乘法)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

随机推荐

  1. 线段树和zkw线段树

    作者作为一个蒟蒻,也是最近才自学了线段树,不对的地方欢迎大佬们评论,但是不要喷谢谢 好啦,我们就开始说说线段树吧 线段树是个支持区间操作和查询的东东,平时的话还是蛮实用的 下面以最基本的区间加以及查询 ...

  2. Pots POJ - 3414 (搜索+记录路径)

    Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22688   Accepted: 9626   Special J ...

  3. PHP递归排序怎么实现的?

    递归算法对于任何一个编程人员来说,应该都不陌生.因为递归这个概念,无论是在PHP语言还是Java等其他编程语言中,都是大多数算法的灵魂.   对于PHP新手来说,递归算法的实现原理可能不容易理解.但是 ...

  4. configParser模块详谈

    前言 使用配置文件来灵活的配置一些参数是一件很常见的事情,配置文件的解析并不复杂,在python里更是如此,在官方发布的库中就包含有做这件事情的库,那就是configParser configPars ...

  5. 17,基于scrapy-redis两种形式的分布式爬虫

    redis分布式部署 1.scrapy框架是否可以自己实现分布式? - 不可以.原因有二. 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls ...

  6. 回顾Scrum学习:《Scrum实战》第4次课【全职的Scrum Master】作业

    回顾Scrum学习   1.回顾目标 1.1 期望结果 了解和学习Scrum,为将来换方向打好理论基础 如果能在目前公司引入和推行也很好,但是根据目前公司的文化氛围来看,推行希望不大 把敏捷思想应用到 ...

  7. ActiveMQ初步学习

    本文主要参考张丰哲大神的简书文章,链接 https://www.jianshu.com/p/ecdc6eab554c JMS,即Java Message Service,通过面向消息中间件(MOM:M ...

  8. service-worker实践

    service-worker虽然已列入标准,但是支持的浏览器还是有限制,还有比较多的问题. 1. 生命周期 注册成功-------installing--------------> 安装成功(i ...

  9. Windows 2008 WinRM和WinRS能帮你做什么?

     介绍    WinRM及WinRS更新包含在Windows Vista, Windows Server 2003 R2, Windows Server 2008 (及 Server 2008 Cor ...

  10. Python框架之Django学习笔记(十四)

    Django站点管理(续·完) 本想昨天更新的,谁曾想昨天竟然是工作日!我就不吐槽昨天加班到十一点多了,需求增加无疑让我等蛋疼不已,忽而想起一首打油诗: 明月几时有,把酒问群友.不知这次版本,今晚能出 ...