bluestein算法
我们熟知的FFT算法实际上是将一个多项式在2n个单位根处展开,将其点值对应相乘,并进行逆变换。然而,由于单位根具有“旋转”的特征(即$w_{m}^{j}=w_{m}^{j+m}$),若多项式次数大于二分之长度,FFT将进行一次长度为2n的循环卷积。bluestein的算法是为了解决在任意长度上的循环卷积问题。
我们知道,任何一个n次多项式都可以被n+1个点值进行表示,因此如果我们选取所有形如$w_{n+1}^{i}$的单位根并带入多项式,进行类似于FFT的变化(这里没有证明),理应得到正确的结果。
设多项式A为$\sum_{i=0}^{n}{a_i*x^i}$,$F_k$为$A(w_{n+1}^{k})$,则有:
$F_k=\sum_{i=0}^{n}{a_i*w_{n+1}^{ik}}$
考虑ik的另外一种组合含义,即有两个盒子,每个盒子分别有i个球和k个球,求有多少种随机拿出两个球且分别属于两个盒子的方法,因此$ik=\tbinom{i+k}{2}-\tbinom{i}{2}-\tbinom{k}{2}$。它的意义在下面推导中可见。
因此$F_k=\sum_{i=0}^{n}{a_i*w_{n+1}^{\tbinom{i+k}{2}-\tbinom{i}{2}-\tbinom{k}{2}}}$
$=w_{n+1}^{-\tbinom{k}{2}}\sum_{i=0}^{n}{a_i*w_{n+1}^{-\tbinom{i}{2}}*w_{n+1}^{\tbinom{i+k}{2}}}$
注意到(i+k)-(i)=k,令$A_{-i}=a_i*w_{n+1}^{-\tbinom{i}{2}}$,$B_i=w_{n+1}^{\tbinom{i}{2}}$。因此,A和B的卷积的第k项即为$F_k$。由于A的下标为负数,我们将A的下标集体加上n。于是,一次bluestein操作花了三次长度为4n的FFT操作。
将多项式转化为点值表达后,我们依葫芦画瓢地将对应位置相乘、进行相应的逆变换(即取单位根的共轭)。而此部分正确性的证明过程是与FFT类似的。
例题:poj2821
1 // 2821
2 #include<cstdio>
3 #include<math.h>
4 #include<cstring>
5 #include<iomanip>
6 #define mod 998244353
7 using namespace std;
8 typedef double ld;
9 const int maxn=(1<<19)+5;
10 const int LIMIT=1<<19;
11 const ld pi=acos(-1);
12 struct com
13 {
14 ld x,y;
15 com(ld a=0,ld b=0):x(a),y(b){}
16 com operator+(const com&A){return com(x+A.x,y+A.y);}
17 com operator-(const com&A){return com(x-A.x,y-A.y);}
18 com operator*(const com&A){return com(x*A.x-y*A.y,x*A.y+y*A.x);}
19 com operator/(const ld&d){return com(x/d,y/d);}
20 com operator/(const com&A){return com(x,y)*com(A.x,-A.y)/(A.x*A.x+A.y*A.y);}
21 void operator/=(const ld&d){x/=d,y/=d;}
22 };
23 int r[maxn];
24 inline void DFT(com*A,int limit,int type)
25 {
26 for(int i=1;i<limit;++i)
27 {
28 r[i]=(r[i>>1]>>1)|((i&1)?(limit>>1):0);
29 if(i<r[i])
30 swap(A[i],A[r[i]]);
31 }
32 for(int len=2;len<=limit;len<<=1)
33 {
34 com w;
35 if(type==1)
36 w=com(cos(pi*2/len),sin(pi*2/len));
37 else
38 w=com(cos(pi*2/len),-sin(pi*2/len));
39 for(int i=0;i<limit;i+=len)
40 {
41 com d(1,0);
42 for(int j=0,p1=i,p2=i+len/2;j<len/2;++j,++p1,++p2)
43 {
44 com a=A[p1],b=A[p2]*d;
45 A[p1]=a+b;
46 A[p2]=a-b;
47 d=d*w;
48 }
49 }
50 }
51 }
52 com tmp1[maxn],tmp2[maxn];
53
54 inline void bluestein(com*A,int n,int type) // n already stands for the number of terms
55 {
56 int limit=1;
57 while(limit<4*n) // 4 times !!!!!!!
58 limit<<=1;
59 for(int i=0;i<limit;++i)
60 tmp1[i]=tmp2[i]=0;
61 for(int i=0;i<n;++i)
62 tmp1[i]=A[i]*com(cos(pi*i*i/n),type*sin(pi*i*i/n));
63 for(int i=0;i<n*2;++i)
64 tmp2[i]=com(cos(pi*(i-n)*(i-n)/n),-type*sin(pi*(i-n)*(i-n)/n));
65 DFT(tmp1,limit,1);
66 DFT(tmp2,limit,1);
67 for(int i=0;i<limit;++i)
68 tmp1[i]=tmp1[i]*tmp2[i];
69 DFT(tmp1,limit,-1);
70 for(int i=0;i<n;++i)
71 A[i]=tmp1[i+n]*com(cos(pi*i*i/n),type*sin(pi*i*i/n))/limit; // dont forget this !!!
72 }
73 com A[maxn],B[maxn],C[maxn];
74 int n;
75 int main()
76 {
77 scanf("%d",&n);
78 --n;
79 for(int i=0;i<=n;++i)
80 scanf("%lf",&A[i].x);
81 for(int i=0;i<=n;++i)
82 scanf("%lf",&B[i].x);
83 bluestein(A,n+1,1);
84 bluestein(B,n+1,1);
85 for(int i=0;i<n+1;++i)
86 A[i]=B[i]/A[i];
87 bluestein(A,n+1,-1);
88 for(int i=0;i<=n;++i)
89 A[i].x/=(n+1);
90 for(int i=0;i<=n;++i)
91 printf("%.4f\n",A[i].x);
92 return 0;
93 }
bluestein算法的更多相关文章
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法)
[POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法) 题面 给出两个长度为\(n\)的序列\(B,C\),已知\(A\)和\(B\)的循环卷积为\(C\),求 ...
- 算法系列:FFT 002
转载自http://blog.jobbole.com/58246/ 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.没有正规计算机科学课程背景 ...
- 快速傅里叶变换(FFT)算法【详解】
快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章 ...
- B树——算法导论(25)
B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...
- 分布式系列文章——Paxos算法原理与推导
Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难. 网上有很多讲解Paxos算法的文章,但是质量参差不齐.看了很多关于Paxos的资 ...
- 【Machine Learning】KNN算法虹膜图片识别
K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- 红黑树——算法导论(15)
1. 什么是红黑树 (1) 简介 上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...
- 散列表(hash table)——算法导论(13)
1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...
随机推荐
- Spring Cloud与Eureka
Spring Cloud与Eureka 一.使用SpringCloud注册中心Eureka 1.1 Eureka和Zookeeper对比 1.1.1 Zookeeper保证CP 1.1.2 Eurek ...
- python模块----paramicko模块 (ssh远程主机并命令或传文件)
paramiko模块 paramicko模块是非标准库模块,需要pip下载 paramicko:模拟ssh登陆linux主机,也有上传下载功能.ansible自动化部署软件底层就有应用paramick ...
- Effective Java读书笔记--类和接口
1.使类和成员的可访问性最小化不指定访问级别,就是包私有.protected = 包私有 + 子类一般private不会被访问到,如果实现了Serializable,可能会泄露.反射.final集合或 ...
- MySQL复合索引探究
复合索引(又称为联合索引),是在多个列上创建的索引.创建复合索引最重要的是列顺序的选择,这关系到索引能否使用上,或者影响多少个谓词条件能使用上索引.复合索引的使用遵循最左匹配原则,只有索引左边的列匹配 ...
- shell脚本的使用该熟练起来了,你说呢?(篇二)
继续前一篇的文章: shell脚本的使用该熟练起来了,你说呢?(篇一) 作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:羽林君 shell传递参数 shell传递参数 我们可以在执行 Shell ...
- Codeforces Round #640 (Div. 4)
比赛链接:https://codeforces.com/contest/1352 A - Sum of Round Numbers 题意 将一个十进制数的每一个非零位分离出来. 代码 #include ...
- A. Little Pony and Expected Maximum
Twilight Sparkle was playing Ludo with her friends Rainbow Dash, Apple Jack and Flutter Shy. But she ...
- hdu5564 Clarke and digits
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission ...
- HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...
- hdu5360 Hiking
Problem Description There are n soda conveniently labeled by 1,2,-,n. beta, their best friends, want ...