博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FFT代码实现
阅读量:6709 次
发布时间:2019-06-25

本文共 4357 字,大约阅读时间需要 14 分钟。

对FFT理论不明白的童鞋可以来这里( FFT学习笔记<理论篇>):

在了解完FFT的理论与算法流程之后,最重要的当然就是写代码啦,下面的两份代码将展示FFT在多项式乘法与高精度乘法中的运用。

在那之前,还有一个重要的东西:

因为下面写的是迭代的FFT代码,而不是采用递归,所以多了一个对rev[]的处理:
我们假设每次将奇数项元素提出来之后,将其放到了序列的最后,如下:

01234567
变成:
02461357
我们一直这样分下去,就变成了:
04261537
我们把其中每个数的二进制翻转过来,发现是递增的:从0到7
那么,rev[i]存的就是将i的二进制位翻转过来的值,也就值i在底层的位置。


题目描述

给定一个n次多项式F(x),和一个m次多项式G(x)。

请求出F(x)和G(x)的卷积。

输入输出格式

输入格式:

第一行2个正整数n,m。

接下来一行n+1个数字,从低到高表示F(x)的系数。

接下来一行m+1个数字,从低到高表示G(x))的系数。

输出格式:

一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数。

输入输出样例

输入样例#1:

1 2
1 2
1 2 1
输出样例#1:
1 4 5 2

#include
#prag\ma GCC optimize("O2")#define N 2097152#define For(a, b, c) for(int a = b; a <= c; ++a)using namespace std;typedef complex
CP;//定义复数类const double pi = 2.0 * acos(-1.0);//这里π是两倍,因为单位复根指数上有2CP A1[N], A2[N];//将两个多项式定义为复数类,方便运算int n, m, n3, s, rev[N];int read(){ int u = 0; char x = getchar(); while(!isdigit(x)) x = getchar(); while(isdigit(x)) u = (u << 3) + (u << 1) + (x ^ 48), x = getchar(); return u;}//读入优化void pre_work(){
//预处理 int bit; n3 = n + m - 1;//结果的次数界 for(s = 1, bit = 0; s < n3; s <<= 1, ++bit) ;//将长度补为2的整数次幂 For(i, 1, s - 1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1)); //这可以表述成:将i的末尾去掉翻转过来,如果末尾是1就在最前面填1}void FFT(CP *A, int l, int f){
//f==-1时,则为IDFT For(i, 0, l - 1) if(i < rev[i]) swap(A[i], A[rev[i]]); //先让元素处于底层位置,这样相邻的一段就是在递归中的同一层的多项式 for(int i = 2; i <= l; i <<= 1){ //枚举区间长度,也就是当前处理的多项式的次数(从底往上->由短到长) CP wi(cos(pi / i), f * sin(pi / i));//计算主根 for(int j = 0; j < l; j += i){ //枚举处理的多项式的开端 CP w(1, 0);//初始值为1 For(k, j, j + (i >> 1) - 1){
//计算当前多项式的结果 CP x = A[k];//这里跟理论篇相同,利用上一层计算当前 CP y = w * A[k + (i >> 1)]; A[k] = x + y; A[k + (i >> 1)] = x - y; w *= wi; } } } if(f == -1) For(i, 0, l - 1) A[i] /= l;//若为IDFT,就除一下}void solve(){ pre_work(); FFT(A1, s, 1); FFT(A2, s, 1);//求值 For(i, 0, s - 1) A1[i] *= A2[i];//逐点相乘 FFT(A1, s, -1);//插值 For(i, 0, n3 - 1) printf("%d ", (int)(A1[i].real() + 0.5)); //输出答案}int main(){#ifndef ONLINE_JUDGE freopen("A.in", "r", stdin); freopen("A.out","w",stdout);#endif n = read(), m = read();//n,m是A1,A2的次数 ++n, ++m;//现在n,m是a1,A2的次数界 For(i, 0, n - 1) A1[i] = read(); For(i, 0, m - 1) A2[i] = read();//读入多项式的系数 solve(); return 0;}

题目描述

给出两个n位10进制整数x和y,你需要计算x*y。

输入输出格式

输入格式:

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

输出格式:

输出一行,即x*y的结果。(注意判断前导0)

输入输出样例

输入样例#1:

1
3
4
输出样例#1:
12

#include
#include
#include
#define N 180005#define For(a, b, c) for(int a = b; a <= c; ++a)using namespace std;typedef complex
CP;const double pi = 2.0 * acos(-1.0);int n, an, s, rev[N], y[N];CP A1[N], A2[N];void pre_work(){ an = (n << 1) - 1; int bit = 0; for(s = 1; s < an; s <<= 1, ++bit) ; For(i, 1, s - 1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));}void FFT(CP *a, int l, int f){ For(i, 0, l - 1) if(i < rev[i]) swap(a[i], a[rev[i]]); for(int i = 2; i <= l; i <<= 1){ CP wi (cos(pi / i), f * sin(pi / i)); for(int j = 0; j < l; j += i){ CP w (1, 0); For(k, j, j + (i >> 1) - 1){ CP x = a[k]; CP y = w * a[k + (i >> 1)]; a[k] = x + y; a[k + (i >> 1)] = x - y; w *= wi; } } } if(f == -1) For(i, 0, l - 1) a[i] /= l;}void solve(){ pre_work(); FFT(A1, s, 1); FFT(A2, s, 1); For(i, 0, s - 1) A1[i] *= A2[i]; FFT(A1, s, -1); For(i, 0, s - 1) y[i] = (int)(A1[i].real() + 0.5); //求出每一位上的值,并赋予y[] For(i, 0, an - 1){
//进位 while(y[i] >= 10){ y[i + 1] += y[i] / 10; y[i] %= 10; ++i; } if(i >= an) an = i + 1; } while(!y[an - 1]) --an;//去前导0 if(!an) ++an;//特判结果为0的情况 For(i, 1, an) printf("%d", y[an - i]);//输出}int main(){#ifndef ONLINE_JUDGE freopen("pro.in", "r", stdin); freopen("pro.out","w",stdout);#endif char c; scanf("%d", &n); For(i, 1, n) cin >> c, A1[n - i] = CP ((c ^ 48), 0); For(i, 1, n) cin >> c, A2[n - i] = CP ((c ^ 48), 0); //将高位置于后面 solve(); return 0;}

转载于:https://www.cnblogs.com/brodrinkwater/p/7527979.html

你可能感兴趣的文章
pandas 用法
查看>>
OpenGL(三)之基础绘制篇
查看>>
uwsgi特性
查看>>
linux下一些重要命令的了解
查看>>
linux——环境变量
查看>>
asp.net验证码生成代码(.cs文件中)
查看>>
Android 查看设备信息
查看>>
怀念学习编程的日子
查看>>
python gettitle v2.0
查看>>
JD 评论晒图爬虫
查看>>
【leetcode】1027. Longest Arithmetic Sequence
查看>>
Reference
查看>>
LeetCode算法题-Convert BST to Greater Tree(Java实现)
查看>>
过滤超链接
查看>>
2-Python3从入门到实战—基础之运算符
查看>>
排序算法
查看>>
SVN与TortoiseSVN实战:从入门到精通
查看>>
空间统计笔记之三(度量地理分布工具集,Measuring Geographic Distributions)
查看>>
记录:网页播放视频
查看>>
vue插件官方文档,做个记录
查看>>