zoukankan      html  css  js  c++  java
  • 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'[]),则有

    $$原式Longleftrightarrowsum_{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'[]),则有:

    $$原式Longleftrightarrowsum_{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
    ",ans[i]);
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    [转]protobuf的编译安装
    [转]OpenMP中几个容易混淆的函数(线程数量/线程ID/线程最大数)以及并行区域线程数量的确定
    C++类中静态数据成员MAP如何初始化
    [转]gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解
    的机器学习开源工具分享
    机器学习常见的采样方法
    图像配准与深度学习方法
    卷积网络中的几何学你了解多少?
    云计算、虚拟化和容器
    在数据科学领域,你掌握这个24个python库就够了!
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5581484.html
Copyright © 2011-2022 走看看