BZOJ_2194_快速傅立叶之二_(FFT+卷积)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=2194
给出序列\(a[0],a[1],...,a[n-1]\)和\(b[0],b[1],...,b[n-1]\).
\(c[k]=\sum_{i=k}^{n-1}a[i]b[i-k]\).
求序列\(c[]\).
分析
这题就是BZOJ_3527_[ZJOI2014]_力_(FFT+卷积)的后半段...
我们来重新分析一下.
首先我们要知道卷积的标准形式:
$$c[i]=\sum_{j=0}^ia[j]b[i-j]$$
很明显这道题并不是卷积的形式,因为卷积是和一定,二这道题却是差一定.
我们其实可以画画图(我脑洞大)...
然后可以发现差一定的时候就是你+1,我也+1,你-1,我也-1.
但是如果我们把其中一个序列倒过来,就变成了你+1,我-1,你-1,我+1,就变成和一定的了!这一点灰常重要!
然后上次我推的那个太不自然,我们这次好好分析一下.
1.把a倒置.
把a倒置之前原式为(我们这里令\(n=n-1\),序列就是\(0~n\),方便一些)
$$\sum_{j=k}^na[i]b[i-k]$$
我们设倒置之后的序列为\(a'[]\),则有
$$原式\Longleftrightarrow\sum_{i=k}^na'[n-i][b[i-k]$$
换元,得到:
$$\sum_{i=0}^{n-k}a'[n-(i+k)]b[(i+k)-k]$$
即
$$\sum_{i=0}^{n-k}a'[n-i-k]b[i]$$
也就是:
$$c[k]=\sum_{i=0}^{n-k}a'[n-i-k]b[i]$$
如果我们设\(A[k]=\sum_{i=1}^ka'[k-i]b[i]\),那么就有:
$$c[k]=A[n-k]$$
这样我们求个卷积,然后倒过来输出就好了.
2.把b倒置
在网上看到好几篇题解都说是倒置b,但是自己推了好长时间都没有推出来,最后发现其中有一点奥妙...
倒置之前原式:
$$\sum_{i=k}^na[i]b[i-k]$$
我们设倒置之后的序列为\(b'[]\),则有:
$$原式\Longleftrightarrow\sum_{i=k}^na[i]b'[n-i+k]$$
换元,得到:
$$\sum_{i=0}^{n-k}a[i+k]b'[n_(i+k)+k]$$
也就是
$$\sum_{i=0}^{n-k}a[i+k]b'[n-i]$$.
可以发现和是定值\(n+k\),但是循环上界却只有\(n-k\).
我们想要得到的应该是:
$$\sum_{i=0}^{n+k}a[i+k]b'[n-i]$$.
我们得到的式子少了一部分.但是观察可以发现,我们得到的式子的循环上界是\(n-k\),对应\(a[n]b'[k]\).
继续向上的\(a[i]\)都为\(0\),而且都后的\(b[i]\)会越界(\(b[负数]\)).
所以这个就可以表示一个卷积了.
$$c[k]=\sum_{i=0}^{n+k}a[n+k-i]b'[i]$$
这个式子是根据原式表示一个卷积二构造出来的等价的式子,只是看起来比较方便而已.
我们设\(B[i]=\sum_{i=0}^ka[i]b[k-i]\).
这样就可以得到
$$c[k]=B[n+k]$$
倒置b的版本:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N=1e5+5,maxn=N<<2; 5 const double pi=acos(-1.0); 6 int n; 7 int rev[maxn]; 8 int f[N],f_[N],g[N],ans[N]; 9 struct cp{ 10 double r,i; 11 cp(double r=0,double i=0):r(r),i(i){} 12 cp operator + (const cp &x) const { return cp(r+x.r,i+x.i); } 13 cp operator - (const cp &x) const { return cp(r-x.r,i-x.i); } 14 cp operator * (const cp &x) const { return cp(r*x.r-i*x.i,r*x.i+i*x.r);} 15 }a[maxn],b[maxn],A[maxn]; 16 void brc(int &n){ 17 memset(rev,-1,sizeof rev); 18 int k=1,l=0; 19 while(k<n) k<<=1, l++; 20 n=k; 21 for(int i=1;i<n-1;i++){ 22 if(rev[i]!=-1) continue; 23 int x=i,y=0,m=l; 24 while(m--) y<<=1, y|=(x&1), x>>=1; 25 rev[i]=y, rev[y]=i; 26 } 27 } 28 void dft(cp *a,int n,int op){ 29 for(int i=1;i<n-1;i++) A[rev[i]]=a[i]; 30 for(int i=1;i<n-1;i++) a[i]=A[i]; 31 for(int m=2;m<=n;m<<=1){ 32 cp wn(cos(2.0*pi/m*op),sin(2.0*pi/m*op)); 33 for(int i=0;i<n;i+=m){ 34 cp w(1); int k=m>>1; 35 for(int j=0;j<k;j++){ 36 cp u=a[i+j],t=w*a[i+j+k]; 37 a[i+j]=u+t; 38 a[i+j+k]=u-t; 39 w=w*wn; 40 } 41 } 42 } 43 if(op==-1)for(int i=0;i<n;i++) a[i].r/=n; 44 } 45 void fft(int *x,int *y,int *ans,int la,int lb){ 46 int len=la+lb-1; 47 brc(len); 48 for(int i=0;i<n;i++) a[i]=cp(x[i]), b[i]=cp(y[i]); 49 dft(a,len,1); dft(b,len,1); 50 for(int i=0;i<len;i++) a[i]=a[i]*b[i]; 51 dft(a,len,-1); 52 for(int i=0;i<len;i++) ans[i]=a[i].r+0.5; 53 } 54 int main(){ 55 scanf("%d",&n); 56 for(int i=0;i<n;i++) scanf("%d%d",&f[i],&g[i]); 57 for(int i=0;i<n;i++) f_[i]=g[n-1-i]; 58 fft(f,f_,ans,n,n); 59 for(int i=n-1;i<n+n-1;i++) printf("%d\n",ans[i]); 60 return 0; 61 }
View Code
转载于:https://www.cnblogs.com/Sunnie69/p/5581484.html
BZOJ_2194_快速傅立叶之二_(FFT+卷积)相关推荐
- 解题报告(二)C、(darkBZOJ 2194) 快速傅立叶之二(FFT、卷积的概念、常用变换)
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- BZOJ2194 快速傅立叶之二 【fft】
题目 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非负整数. 输入格式 ...
- bzoj2194 快速傅立叶之二
2194: 快速傅立叶之二 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 1730 Solved: 1026 [Submit][Status][D ...
- bzoj2194: 快速傅立叶之二
了解到了FFT求卷积,但是还是感性的认识.. 取反就可以了.输出一定要加int!!!! #include<cstdio> #include<iostream> #include ...
- bzoj 2194 快速傅立叶之二
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2194 因为卷积的第 k 项是 sigma(i=0~k)a[ i ]*b[ k-i ] ,也就 ...
- [BZOJ]2194: 快速傅立叶之二
题目大意:给定序列a,b,求序列c满足c[k]=sigma(a[i]*b[i-k]) (k<=i<n).(n<=10^5) 思路:观察发现就是普通的卷积反一反(翻转ab其中一个后做卷 ...
- BZOJ-2194 快速傅立叶之二
FFT模版题. 观察题目,我们可以发现,只要把序列b倒过来,再联想一下乘法运算... 我们会发现,将序列a和序列b当作100进制数,做一次乘法,然后从低到高每一位便是答案了(乘完无需进位) #incl ...
- 【刷题】BZOJ 2194 快速傅立叶之二
Description 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非 ...
- BZOJ_2179_FFT快速傅立叶_(FFT)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2179 超大整数乘法 分析 FFT模板题. 把数字看成是多项式,x是10.然后用FFT做多项式乘 ...
最新文章
- shell中引号的使用方法
- for...in和 for...of
- UA MATH574M 统计学习II 二元分类
- selenium python怎么读_selenium+Python中的面试总结
- 港媒:AI技术有望助力中国核潜艇升级
- 万水千山ABP - 弹出对话框禁用回车
- Django(part41)--中间键Middleware
- ARC115D-Odd Degree【dp,欧拉回路】
- HTTPS时代已来,你做好准备了吗?
- java迭代器cas,java提高篇(三十)-Iterator - Java 技术驿站-Java 技术驿站
- java gson 工具类_GSON 实体 转换工具类
- c++批量重命名_手把手教你用Python批量给图片添加水印 | 知了干货分享
- XML相关的安全漏洞-XXE,XPATH小结(XXE注入、XPATH注入)
- 在ASP.NET 3.5中使用新的ListView控件(5)
- java jtextfield 高度_java - 固定的JTextField的高度和宽度 - 堆栈内存溢出
- c++中recvfrom函数_通俗易懂:快速理解网络编程中5种IO模型
- 防范项目中人员频繁变动的风险
- C# 赛邮接口短信API验证demo
- Vite图片压缩(vite-plugin-imagemin) imagemin error: XXXX解决办法
- matlab convexhull,使用convex_hull计算体积为0