FFT(Fast Fourier Transformation——快速傅里叶变换)可以用来快速求多项式乘法,相当于系数向量的卷积,通俗点说就是给定a和b数组,然后求c数组:

for(int i=0; i<n; ++i)for(int j=0; j<n; ++j)c[i+j] += a[i]*b[j];

FFT就是用来快速求出上述的c数组,FFT分成如下两个过程:

DFT——Discrete Fourier Transform 离散傅里叶逆变换
IDFT——Inverse Discrete Fourier Transform 离散傅里叶逆变换

通过计算机算法可以O(nlogn)执行以上两个过程,具体做法和证明请参考其他资料。那么FFT有什么用呢?比如大数乘法,即相当于变项X=10的多项式乘法,那么我们对它的系数求卷积就完成了。

1.HDU 1402

A * B Problem Plus

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 24638    Accepted Submission(s): 6276

Problem Description
Calculate A * B.
Input
Each line will contain two integers A and B. Process to end of file.

Note: the length of each integer will not exceed 50000.

Output
For each case, output A * B in one line.
Sample Input
1210002
Sample Output
22000
Author
DOOM III
题意:大数乘法。
思路:模板题。 
# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <complex>
using namespace std;
typedef complex <double> cp;
const int maxn = 550010;
const double pi = acos(-1.0);
char sa[maxn], sb[maxn];
int lena, lenb, N, n=1, l=0, res[maxn], R[maxn];
cp a[maxn], b[maxn];
void fft(cp *A, int f)
{for(int i=0; i<n; ++i)if(i<R[i]) swap(A[i], A[R[i]]);for(int i=1; i<n; i<<=1){cp wn(cos(pi/i), sin(f*pi/i)), x, y;for(int j=0; j<n; j+=(i<<1)){cp w(1, 0);for(int k=0; k<i; ++k,w*=wn){x = A[j+k], y = w*A[i+j+k];A[j+k] = x+y;A[i+j+k] = x-y;}}}
}
int main()
{while(~scanf("%s%s",sa,sb)){n = 1; N = l = 0;memset(res, 0, sizeof(res));lena = strlen(sa), lenb = strlen(sb);while(n<=lena+lenb) n<<=1,++l;//补成2的幂次大小for(int i=0; i<lena; ++i) a[i] = sa[lena-i-1]-'0';for(int i=lena; i<=n; ++i) a[i] = 0;for(int i=0; i<lenb; ++i) b[i] = sb[lenb-i-1]-'0';for(int i=lenb; i<=n; ++i) b[i] = 0;for(int i=0; i<=n; ++i) R[i] = (R[i>>1]>>1)|((i&1)<<(l-1));fft(a, 1);fft(b, 1);for(int i=0; i<=n; ++i) a[i] *= b[i];fft(a, -1);for(int i=0; i<=lena+lenb; ++i){res[i] += int(a[i].real()/n+0.5);res[i+1] += res[i]/10;res[i] %= 10;if(res[i]>0) N=i;}for(int i=N; ~i; --i)putchar(res[i]+'0');puts("");}return 0;
}

2.HDU4609:

3-idiots

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6656    Accepted Submission(s): 2335

Problem Description
King OMeGa catched three men who had been streaking in the street. Looking as idiots though, the three men insisted that it was a kind of performance art, and begged the king to free them. Out of hatred to the real idiots, the king wanted to check if they were lying. The three men were sent to the king's forest, and each of them was asked to pick a branch one after another. If the three branches they bring back can form a triangle, their math ability would save them. Otherwise, they would be sent into jail.
However, the three men were exactly idiots, and what they would do is only to pick the branches randomly. Certainly, they couldn't pick the same branch - but the one with the same length as another is available. Given the lengths of all branches in the forest, determine the probability that they would be saved.
Input
An integer T(T≤100) will exist in the first line of input, indicating the number of test cases.
Each test case begins with the number of branches N(3≤N≤105).
The following line contains N integers a_i (1≤a_i≤105), which denotes the length of each branch, respectively.
Output
Output the probability that their branches can form a triangle, in accuracy of 7 decimal places.
Sample Input
241 3 3 442 3 3 4
Sample Output
0.50000001.0000000

题意:给N条棍子,任选3条能够组成三角形的概率。

思路:用FFT求出用2条棍子组成长度为i的棍子的方案数,然后枚举选取的最长棍子,减去非法的方案即可。

# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <algorithm>
# include <complex>
using namespace std;
typedef long long LL;
typedef complex <double> cp;
const int maxn = 550010;
const double pi = acos(-1.0);
int lena, lenb, n=1, l=0, N, R[maxn], arr[maxn];
cp a[maxn];
LL res[maxn], ans;
void fft(cp *A, int f)
{for(int i=0; i<n; ++i)if(i<R[i]) swap(A[i], A[R[i]]);for(int i=1; i<n; i<<=1){cp wn(cos(pi/i), sin(f*pi/i)), x, y;for(int j=0; j<n; j+=(i<<1)){cp w(1, 0);for(int k=0; k<i; ++k,w*=wn){x = A[j+k], y = w*A[i+j+k];A[j+k] = x+y;A[i+j+k] = x-y;}}}
}
int main()
{int T, x;scanf("%d",&T);while(T--){ans = 0;n = 1; l = 0;scanf("%d",&N);memset(res, 0, sizeof(res));int imax = 0;for(int i=1; i<=N; ++i){scanf("%d",&arr[i]);imax = max(imax, arr[i]);++res[arr[i]];}while(n<=imax*2) n<<=1,++l;for(int i=0; i<n; ++i) a[i] = res[i];for(int i=0; i<=n; ++i) R[i] = (R[i>>1]>>1)|((i&1)<<(l-1));fft(a, 1);for(int i=0; i<n; ++i) a[i] *= a[i];fft(a, -1);for(int i=0; i<n; ++i) res[i] = LL(a[i].real()/n+0.5);for(int i=1; i<=N; ++i) --res[arr[i]*2];for(int i=0; i<n; ++i) res[i]>>=1;for(int i=1; i<=n; ++i) res[i] += res[i-1];sort(arr+1, arr+1+N);for(int i=1; i<=N; ++i){ans += res[n]-res[arr[i]];ans -= 1LL*(N-i)*(N-i-1)/2;//都大于arr[i]ans -= 1LL*(N-i)*(i-1);//一条大于arr[i]ans -= N-1;//一条等于arr[i]}printf("%.7f\n",ans*1.0/(1LL*N*(N-1)*(N-2)/6));}return 0;
}

3.HDU 5307

He is Flying

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1479    Accepted Submission(s): 419

Problem Description
JRY wants to drag racing along a long road. There are n sections on the road, the i-th section has a non-negative integer length si. JRY will choose some continuous sections to race (at an unbelievable speed), so there are totally n(n+1)2 different ways for him to ride. If JRY rides across from the i-th section to the j-th section, he would gain j−i+1 pleasure. Now JRY wants to know, if he tries all the ways whose length is s, what's the total pleasure he can get. Please be aware that in the problem, the length of one section could be zero, which means that the length is so trivial that we can regard it as 0.
Input
The first line of the input is a single integer T (T=5), indicating the number of testcases.

For each testcase, the first line contains one integer n. The second line contains n non-negative integers, which mean the length of every section. If we denote the total length of all the sections as s, we can guarantee that 0≤s≤50000 and 1≤n≤100000.

Output
For each testcase, print s+1 lines. The single number in the i-th line indicates the total pleasure JRY can get if he races all the ways of length i−1.
Sample Input
231 2 340 1 2 3
Sample Output
01130231316027
Author
XJZX

题意:给N个数,问所有和为X的连续区间的长度总和是多少,X从0到sum都要输出答案。

思路:连续区间容易想到前缀和,所有区间的贡献,容易想到前缀和取反后跑FFT,前缀和作为多项式指数(数组下标),但是由于FTT是乘法,无法将贡献跟多项式的系数(数组的值)联系起来,那么我们先求出sum[i]代表和为i的连续区间的右界总和,再求出sum2[i]代表和为i的连续区间的左界总和,sum[i]-sum2[i]就是和为i的答案,这两者就容易求了。因为用这里用FFT加速前缀和相减,所以0要特殊处理!另外这题不能用STL进行复数运算否则卡精度。

#include <bits/stdc++.h>
using namespace std;
#define N 110000
#define ll long long
#define ld long double
const ld PI=acos(-1);
int T,n;
int sum[N],cnt;
ll ans[N],pre[N];
struct cp
{ld x,y;cp(){}cp(ld x,ld y):x(x),y(y){}friend cp operator + (const cp &r1,const cp &r2){return cp(r1.x+r2.x,r1.y+r2.y);}friend cp operator - (const cp &r1,const cp &r2){return cp(r1.x-r2.x,r1.y-r2.y);}friend cp operator * (const cp &r1,const cp &r2){return cp(r1.x*r2.x-r1.y*r2.y,r1.x*r2.y+r2.x*r1.y);}
}a[N<<1],b[N<<1],c[N<<1];
void init()
{memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));
}
void FFT(cp *a,int len,int type)
{int t=0;for(int i=0;i<len;i++){if(i>t)swap(a[i],a[t]);for(int j=len>>1;(t^=j)<j;j>>=1);}for(int i=2;i<=len;i<<=1){cp wn(cos(2*PI*type/i),sin(2*PI*type/i));for(int j=0;j<len;j+=i){cp t,w(1,0);for(int k=0;k<(i>>1);k++,w=w*wn){t=w*a[j+k+(i>>1)];a[j+k+(i>>1)]=a[j+k]-t;a[j+k]=a[j+k]+t;}}}
}
void solve(cp *a,cp *b,cp *c,int len)
{FFT(a,len,1);FFT(b,len,1);for(int i=0;i<len;i++)c[i]=a[i]*b[i];FFT(c,len,-1);
}
int main()
{for(int i=1;i<=100000;i++)pre[i]=pre[i-1]+(ll)i*(i+1)/2;scanf("%d",&T);while(T--){memset(ans,0,sizeof(ans));scanf("%d",&n);cnt=0;for(int i=1;i<=n;i++){scanf("%d",&sum[i]);if(sum[i]==0)cnt++;else ans[0]+=pre[cnt],cnt=0;sum[i]+=sum[i-1];}ans[0]+=pre[cnt];int len=1;for(;len<=sum[n]<<1;len<<=1);init();for(int i=1;i<=n;i++)a[sum[i]].x+=i,b[sum[n]-sum[i-1]].x++;solve(a,b,c,len);for(int i=1;i<=sum[n];i++)ans[i]+=(ll)(c[i+sum[n]].x/len+0.1);init();for(int i=1;i<=n;i++)a[sum[i]].x++,b[sum[n]-sum[i-1]].x+=i-1;solve(a,b,c,len);for(int i=1;i<=sum[n];i++)ans[i]-=(ll)(c[i+sum[n]].x/len+0.1);for(int i=0;i<=sum[n];i++)printf("%lld\n",ans[i]);}return 0;
}

4.51nod 1690 区间求和2 

给出一个长度为n的数组a。区间[L,R]的值为 ∑R−Li=0a[L+i]∗a[R−i]

求所有长度为质数的区间的值的总和。

Input
第一行一个数n(1<=n<=100000)
第二行n个数,表示数组a(0<=a[i]<=1000)
Output
一个数表示答案,答案对10^9+7取模。
Input示例
4
1 2 3 4
Output示例
75

思路:考虑每一个点对(i,j)的贡献,显然i和j的奇偶性相同才有贡献(除了长度为2的区间特殊处理),那么(i,j)的贡献显然是

a[i]*a[j]*F[min(i+j−1,2n+1−i−j)]] - a[i]*a[j]*F[j-i)]。其中F[i]表示1~i有几个质数(不包括2),即右边和左边能延伸的长度的较少值,公式左边FFT直接搞算出res[i]表示下标和为i的二元组总和,右边也是FFT,res[i]理论应该算出区间长度为i的二元组总和,但是这样算不了,需要将原数组反转一下,具体看代码纸上模拟下就ok。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e5+30;
typedef complex <double> cp;
const double pi = acos(-1.0);
const LL mod = 1e9+7;
int n=1, l=0,N, R[maxn], c[maxn], p[maxn];
LL ans=0, res[maxn];
cp a[maxn], b[maxn];
void fft(cp *A, int f)
{for(int i=0; i<n; ++i)if(i<R[i]) swap(A[i], A[R[i]]);for(int i=1; i<n; i<<=1){cp wn(cos(pi/i), sin(f*pi/i)), x, y;for(int j=0; j<n; j+=(i<<1)){cp w(1, 0);for(int k=0; k<i; ++k,w*=wn){x = A[j+k], y = w*A[i+j+k];A[j+k] = x+y;A[i+j+k] = x-y;}}}
}
void init()
{for(int i=3; i<=300000; ++i){int flag = 1;for(int j=2; j<=sqrt(i); ++j){if(i%j==0){flag = 0;break;}}p[i] = p[i-1]+flag;}
}
inline void add(LL &x, LL y)
{x += y%mod;x = (x%mod+mod)%mod;
}
int main()
{init();scanf("%d",&N);for(int i=1; i<=N; ++i){scanf("%d",&c[i]);if(i>1) add(ans, c[i]*c[i-1]%mod*2);}while(n<=N+N) n<<=1, ++l;for(int i=0; i<=N; ++i) a[i] = c[i];for(int i=0; i<=n; ++i) R[i] = (R[i>>1]>>1)|((i&1)<<(l-1));fft(a, 1);for(int i=0; i<=n; ++i) a[i] *= a[i];fft(a, -1);for(int i=1; i<=N+N; ++i) res[i] = LL(a[i].real()/n+0.5)%mod;for(int i=4; i<=N+1; i+=2) add(ans, res[i]*p[i-1]);for(int i=N+2; i<=N+N; ++i) if(!(i&1))add(ans, res[i]*p[2*N+1-i]);memset(a, 0, sizeof(a));for(int i=1; i<=N; ++i){a[i] = c[i];b[i] = c[N-i+1];}fft(a, 1);fft(b, 1);for(int i=0; i<=n; ++i) a[i] *= b[i];fft(a, -1);for(int i=1; i<=N+N; ++i) res[i] = LL(a[i].real()/n+0.5);for(int i=3; i<=N; i+=2)add(ans, p[i-1]*res[N-i+2]%mod*2*-1);printf("%lld\n",ans);return 0;
}

数论:快速傅里叶变换FFT题集相关推荐

  1. [模板] 快速傅里叶变换(FFT)

    快速傅里叶变换FFT 多项式 转换 快速傅里叶变换 铺垫 定理 算法构建 IFFT 递归版FFT&IFFT 迭代版FFT&IFFT 蝴蝶效应 Code 后记 多项式 假设有nnn次多项 ...

  2. 基于python的快速傅里叶变换FFT(二)

    基于python的快速傅里叶变换FFT(二) 本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点   FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算 ...

  3. 基于python的快速傅里叶变换FFT(一)

    基于python的快速傅里叶变换FFT(一) FFT可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了.这就是很多信号分析采用FFT变换的原因. ...

  4. MIT 线性代数 Linear Algebra 26:复矩阵,傅里叶矩阵, 快速傅里叶变换 FFT

    这一讲我们来讲一下复矩阵.线性代数中,复矩阵是避免不了的话题,因为一个简单实矩阵都有可能有复数特征值. 复矩阵 我们着重看一下复矩阵和实矩阵在运算上的区别. 距离 首先,一个复数向量的的距离求法发生了 ...

  5. Java中实现快速傅里叶变换FFT

    Java中实现快速傅里叶变换FFT 一.概述 1.傅里叶变换(FT) 2.离散傅里叶变换(DFT) 3.快速傅里叶变换(FFT) 1)单位根 2)快速傅里叶变换的思想 3)蝶形图 4)快速傅里叶变换的 ...

  6. OpenCV快速傅里叶变换(FFT)用于图像和视讯流的模糊检测

    OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测 翻译自[OpenCV Fast Fourier Transform (FFT) for blur detection in images ...

  7. Matlab如何进行利用离散傅里叶变换DFT (快速傅里叶变换FFT)进行频谱分析

    文章目录 1. 定义 2. 变换和处理 3. 函数 4. 实例演示 例1:单频正弦信号(整数周期采样) 例2:单频正弦信号(非整数周期采样) 例3:含有直流分量的单频正弦信号 例4:正弦复合信号 例5 ...

  8. 快速傅里叶变换FFT进行频谱分析(matlab)

    快速傅里叶变换FFT进行频谱分析(matlab) 本章摘要:FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了 ...

  9. Java编程实现快速傅里叶变换FFT

    快速傅里叶变换的时间复杂度分析 1 快速傅里叶变换FFT 1.1 理论分析 1.1.1 离散傅里叶变换 1.1.2 快速傅里叶变换 1.2 编程实现 1.2.1 算法思想 1.2.2 实验结果 1 快 ...

  10. 快速傅里叶变换FFT C语言实现 可用于嵌入式系统进行模拟采样频谱分析

    快速傅里叶变换C语言实现 模拟采样进行频谱分析 FFT是DFT的快速算法用于分析确定信号(时间连续可积信号.不一定是周期信号)的频率(或相位.此处不研究相位)成分,且傅里叶变换对应的 ω \omega ...

最新文章

  1. sql server 常用函数
  2. html的左侧菜单栏,HTML 之 左侧菜单
  3. PHP获取数组最后一个值的2种方法
  4. 【Android开发】线程与消息处理-Handler消息传递机制之Looper
  5. 转 Java中final、finally、finalize的区别与用法
  6. 领会CSS,实际中的研究
  7. 深度linux系统gho,深度技术ghost版的win7操作系统下载
  8. factorybean 代理类不能按照类型注入_彻底搞懂依赖注入(一)Bean实例创建过程
  9. 三维绘图plot3命令ezplot3命令三维网格命令mesh命令
  10. Linux隧道isatap(sit模式)
  11. wxml 判断 小程序_微信小程序WXML-小样儿960
  12. “WebProxyWrapper”的对象强制转换为类型“System.Net.WebProxy
  13. 运动模糊(MotionBlur)
  14. ORACLE的递归查询
  15. WINCE下模拟鼠标点击,移动
  16. Ubuntu18解决:Not creating XLA devices, tf_xla_enable_xla_devices not set
  17. IDC机房网络系列视频
  18. C#设计模式(4)-Simple Factory Pattern
  19. git执行任何操作都特别慢,怎么解决?
  20. iPhone界面跳转

热门文章

  1. 简信CRM:CRM科学服务体系,促进企业销售增长
  2. 微型计算机MC定义,mc是什么意思
  3. 218分照样可以成为同声传译研究生3
  4. 值钱的木头——前缀和思想
  5. 天池- IJCAI-18 阿里妈妈搜索广告转化预测(完整版代码,数据集等总结)
  6. Rockchip | Rockusb工具
  7. OpenERP 7.0入门(一):安装及开发环境部署
  8. 大数乘方运算-C语言
  9. 大理大学 计算机研究生分数线,大理大学2018年研究生复试分数线
  10. 最牛X得“高考”作文