fft模板
来源:互联网 发布:笔记本电脑散热器软件 编辑:程序博客网 时间:2024/06/06 03:25
整理了一下目前所写过的fft题目(使用kuangbin模板)
首先需要明白一个概念,fft是用来求卷积的,他可以把离散的xx变成连续的xx,然后把n^2的时间复杂度变成nlogn。
比如现在计算28*76的值就可以使用卷积计算。
第一步:先把76逆置成67
第二步:
28
67 得8*6=48,放入a数组,a[0]=48
第三步:
28
67 得2*6+8*7=68,a[1]=68
第四步:
28
67 得2*7=14,a[2]=14
第五步:
a数组:14 68 48
个位为48%10=8,进4
十位为(68+4)%10=2,进7
百位为(14+7)%10=1,进2
千位为2
值为2128
1.hdu1402
大致题意:求a*b
测试案例:
input:
1
2
1000
2
output:
2
2000
解题思路:这题就是上面那两个一维卷积卷了得出的结果
代码:
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <math.h>using namespace std;const double PI = acos(-1.0);//复数结构体struct complex{ double r,i; complex(double _r = 0.0,double _i = 0.0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); }};/* * 进行FFT和IFFT前的反转变换。 * 位置i和 (i二进制反转后位置)互换 * len必须去2的幂 */void change(complex y[],int len){ int i,j,k; for(i = 1, j = len/2;i < len-1; i++) { if(i < j)swap(y[i],y[j]); //交换互为小标反转的元素,i<j保证交换一次 //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的 k = len/2; while( j >= k) { j -= k; k /= 2; } if(j < k) j += k; }}/* * 做FFT * len必须为2^k形式, * on==1时是DFT,on==-1时是IDFT */void fft(complex y[],int len,int on){ change(y,len); for(int h = 2; h <= len; h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); for(int j = 0;j < len;j+=h) { complex w(1,0); for(int k = j;k < j+h/2;k++) { complex u = y[k]; complex t = w*y[k+h/2]; y[k] = u+t; y[k+h/2] = u-t; w = w*wn; } } } if(on == -1) for(int i = 0;i < len;i++) y[i].r /= len;}const int MAXN = 200010;complex x1[MAXN],x2[MAXN];char str1[MAXN/2],str2[MAXN/2];int sum[MAXN];int main(){ while(scanf("%s%s",str1,str2)==2) { int len1 = strlen(str1); int len2 = strlen(str2); int len = 1; while(len < len1*2 || len < len2*2)len<<=1; for(int i = 0;i < len1;i++) x1[i] = complex(str1[len1-1-i]-'0',0); for(int i = len1;i < len;i++) x1[i] = complex(0,0); for(int i = 0;i < len2;i++) x2[i] = complex(str2[len2-1-i]-'0',0); for(int i = len2;i < len;i++) x2[i] = complex(0,0); //求DFT fft(x1,len,1); fft(x2,len,1); for(int i = 0;i < len;i++) x1[i] = x1[i]*x2[i]; fft(x1,len,-1); for(int i = 0;i < len;i++) sum[i] = (int)(x1[i].r+0.5); for(int i = 0;i < len;i++) { sum[i+1]+=sum[i]/10; sum[i]%=10; } len = len1+len2-1; while(sum[len] <= 0 && len > 0)len--; for(int i = len;i >= 0;i--) printf("%c",sum[i]+'0'); printf("\n"); } return 0;}
2.hihocoder1388(2016 acm 北京网络赛e题)
大致题意:给出等长的A,B序列,求
测试案例:
input:
2
9
3 0 1 4 1 5 9 2 6
5 3 5 8 9 7 9 3 2
5
1 2 3 4 5
2 3 4 5 1
output:
80
0
解题思路:这题其实也是2个一维卷积的应用。公式可以化简为
此时我们可以把一个串变长一倍,再用另一个串反转求他们的卷积,如
1 2 3 4 5 1 2 3 4 5与2 3 4 5 1的卷积,然后就能看出有一串连续位置的fft值即为结果,求出其中最小值即可,又因为fft的精度问题,直接fft很可能WA,所以需要在
for(int i = 0;i < len;i++) sum[i]= (int)(x1[i].r+0.5);
这种地方直接比较x1[i].r的大小,然后得出什么位置最小,重新按数组计算即可。
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>using namespace std;typedef long long ll;const double PI = acos(-1.0);//复数结构体struct complex{ double r,i; complex(double _r = 0.0,double _i = 0.0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); }};/* * 进行FFT和IFFT前的反转变换。 * 位置i和 (i二进制反转后位置)互换 * len必须去2的幂 */void change(complex y[],int len){ int i,j,k; for(i = 1, j = len/2;i < len-1; i++) { if(i < j)swap(y[i],y[j]); //交换互为小标反转的元素,i<j保证交换一次 //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的 k = len/2; while( j >= k) { j -= k; k /= 2; } if(j < k) j += k; }}/* * 做FFT * len必须为2^k形式, * on==1时是DFT,on==-1时是IDFT */void fft(complex y[],int len,int on){ change(y,len); for(int h = 2; h <= len; h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); for(int j = 0;j < len;j+=h) { complex w(1,0); for(int k = j;k < j+h/2;k++) { complex u = y[k]; complex t = w*y[k+h/2]; y[k] = u+t; y[k+h/2] = u-t; w = w*wn; } } } if(on == -1) for(int i = 0;i < len;i++) y[i].r /= len;}const int maxn = 400010;complex x1[maxn],x2[maxn];ll a[maxn],b[maxn],num[maxn],sum;int main(){ int T,i,j,len,n,len1,len2; scanf("%d",&T); while (T--) { scanf("%d",&n); sum=0; len1=2*n; len2=n; for (i=0;i<n;i++) { scanf("%lld",&a[n-i-1]); a[2*n-i-1]=a[n-i-1]; sum+=a[n-i-1]*a[n-i-1]; } for (i=0;i<n;i++) { scanf("%lld",&b[n-i-1]); sum+=b[n-i-1]*b[n-i-1]; } len=1; while (len<len1*2) len<<=1; for (i=0;i<len1;i++) { x1[i]=complex(a[i],0); } for (i=len1;i<len;i++) { x1[i]=complex(0,0); } for (i=0;i<len2;i++) { x2[i]=complex(b[len2-i-1],0); } for (i=len2;i<len;i++) { x2[i]=complex(0,0); } fft(x1,len,1); fft(x2,len,1); for(int i = 0;i < len;i++) x1[i] = x1[i]*x2[i]; fft(x1,len,-1); ll ans=0; double temp=-1; int pos; for(i = n-1;i < 2*n;i++) { if (temp<x1[i].r) { temp=x1[i].r; pos=i; } } int t=0; for (i=pos;i>pos-n;i--) { ans+=a[i]*b[--len2]; } printf("%lld\n",sum-2*ans); } return 0;}
0 0
- (模板)FFT
- FFT模板
- FFT模板
- FFT模板
- FFT模板
- fft模板
- FFT模板
- FFT 模板
- FFT模板
- FFT模板
- FFT模板
- FFT模板
- 【模板】FFT
- FFT模板
- 【模板】FFT模板
- FFT乘法模板
- 高精度乘法FFT 模板
- [UOJ34]FFT && NTT 模板
- 判断android手机中有无某个程序
- iOS APP 如何做才安全
- 开发网络程序验证效率和稳定性时需要注意的几个问题
- iOS UIView
- 利用 Android Studio 和 Gradle 打包多版本APK
- fft模板
- 引用的释放管理
- 1.Basic Structure
- java mysql batchquery批量添加
- Provisional headers are shown 错误可能原因
- Test
- Dubbo初识
- Android中PathEffect的使用
- mysql 时间相减