描述


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+卷积)相关推荐

  1. 解题报告(二)C、(darkBZOJ 2194) 快速傅立叶之二(FFT、卷积的概念、常用变换)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  2. BZOJ2194 快速傅立叶之二 【fft】

    题目 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非负整数. 输入格式 ...

  3. bzoj2194 快速傅立叶之二

    2194: 快速傅立叶之二 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 1730  Solved: 1026 [Submit][Status][D ...

  4. bzoj2194: 快速傅立叶之二

    了解到了FFT求卷积,但是还是感性的认识.. 取反就可以了.输出一定要加int!!!! #include<cstdio> #include<iostream> #include ...

  5. bzoj 2194 快速傅立叶之二

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2194 因为卷积的第 k 项是 sigma(i=0~k)a[ i ]*b[ k-i ] ,也就 ...

  6. [BZOJ]2194: 快速傅立叶之二

    题目大意:给定序列a,b,求序列c满足c[k]=sigma(a[i]*b[i-k]) (k<=i<n).(n<=10^5) 思路:观察发现就是普通的卷积反一反(翻转ab其中一个后做卷 ...

  7. BZOJ-2194 快速傅立叶之二

    FFT模版题. 观察题目,我们可以发现,只要把序列b倒过来,再联想一下乘法运算... 我们会发现,将序列a和序列b当作100进制数,做一次乘法,然后从低到高每一位便是答案了(乘完无需进位) #incl ...

  8. 【刷题】BZOJ 2194 快速傅立叶之二

    Description 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非 ...

  9. BZOJ_2179_FFT快速傅立叶_(FFT)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2179 超大整数乘法 分析 FFT模板题. 把数字看成是多项式,x是10.然后用FFT做多项式乘 ...

最新文章

  1. shell中引号的使用方法
  2. for...in和 for...of
  3. UA MATH574M 统计学习II 二元分类
  4. selenium python怎么读_selenium+Python中的面试总结
  5. 港媒:AI技术有望助力中国核潜艇升级
  6. 万水千山ABP - 弹出对话框禁用回车
  7. Django(part41)--中间键Middleware
  8. ARC115D-Odd Degree【dp,欧拉回路】
  9. HTTPS时代已来,你做好准备了吗?
  10. java迭代器cas,java提高篇(三十)-Iterator - Java 技术驿站-Java 技术驿站
  11. java gson 工具类_GSON 实体 转换工具类
  12. c++批量重命名_手把手教你用Python批量给图片添加水印 | 知了干货分享
  13. XML相关的安全漏洞-XXE,XPATH小结(XXE注入、XPATH注入)
  14. 在ASP.NET 3.5中使用新的ListView控件(5)
  15. java jtextfield 高度_java - 固定的JTextField的高度和宽度 - 堆栈内存溢出
  16. c++中recvfrom函数_通俗易懂:快速理解网络编程中5种IO模型
  17. 防范项目中人员频繁变动的风险
  18. C# 赛邮接口短信API验证demo
  19. Vite图片压缩(vite-plugin-imagemin) imagemin error: XXXX解决办法
  20. matlab convexhull,使用convex_hull计算体积为0

热门文章

  1. chrome 扩展开发 - 如何获得iframe中的元素 和 相关问题解答
  2. spring总结2——SpringIOC以及DI
  3. 用python写一个王者荣耀框架
  4. 深度学习评价指标系列——CDF累积分布函数(分布函数)
  5. 34.QLineEdit
  6. 制作initrd.img
  7. 组播IP地址的使用范围规定
  8. 小红书流量规则是什么,推荐机制解读
  9. 【离子注入】TRIM2013pro仿真卡屏解决方法(win10)
  10. QPM 之同类 PM 对比