• 【BZOJ】2194: 快速傅立叶之二


    http://www.lydsy.com/JudgeOnline/problem.php?id=2194

    题意:求$c[k]=sum_{k<=i<n} a[i]b[i-k], n<=10^5$

    #include <bits/stdc++.h>
    using namespace std;
    struct cp {
    	double x, y;
    	cp(double _x=0, double _y=0):x(_x),y(_y) {}
    	cp operator+(const cp &a) { return cp(x+a.x, y+a.y); }
    	cp operator-(const cp &a) { return cp(x-a.x, y-a.y); }
    	cp operator*(const cp &a) { return cp(x*a.x-y*a.y, x*a.y+y*a.x); }
    };
    const int N=400005;
    const double pi=acos(-1);
    int rev[N];
    void dft(cp *a, int n, int flag) {
    	static cp A[N], u, v;
    	static int i, j, m, mid;
    	for(i=0; i<n; ++i) A[rev[i]]=a[i];
    	for(i=0; i<n; ++i) a[i]=A[i];
    	for(m=2; m<=n; m<<=1) {
    		cp wn(cos(pi*2/m), sin(pi*2/m)*flag);
    		for(i=0; i<n; i+=m) {
    			mid=m>>1; cp w(1);
    			for(j=0; j<mid; ++j) {
    				u=a[i+j], v=a[i+j+mid]*w;
    				a[i+j]=u+v;
    				a[i+j+mid]=u-v;
    				w=w*wn;
    			}
    		}
    	}
    	if(flag==-1) for(i=0; i<n; ++i) a[i].x/=n;
    }
    inline void init(int &len) {
    	static int k, t, j, r; k=1; t=0;
    	while(k<len) k<<=1, ++t;
    	len=k;
    	for(int i=0; i<len; ++i) {
    		k=i; j=t; r=0;
    		while(j--) r<<=1, r|=k&1, k>>=1;
    		rev[i]=r;
    	}
    }
    void fft(int *a, int *b, int *c, int la, int lb) {
    	static cp x[N], y[N];
    	int len=la+lb-1;
    	init(len);
    	for(int i=0; i<len; ++i) x[i].x=a[i], x[i].y=0;
    	for(int i=0; i<len; ++i) y[i].x=b[i], y[i].y=0;
    	dft(x, len, 1); dft(y, len, 1);
    	for(int i=0; i<len; ++i) x[i]=x[i]*y[i];
    	dft(x, len, -1);
    	for(int i=0; i<len; ++i) c[i]=x[i].x+0.5;
    }
    int x[N], y[N], a[N], n;
    int main() {
    	scanf("%d", &n);
    	for(int i=0; i<n; ++i) scanf("%d%d", &x[i], &y[i]);
    	for(int i=0; i<n; ++i) a[i]=x[n-1-i];
    	fft(y, a, x, n, n);
    	for(int i=0; i<n; ++i) a[i]=x[n-1-i];
    	for(int i=0; i<n; ++i) printf("%d
    ", a[i]);
    	return 0;
    }
    

      


    复习了下fft...能码出来真是极好的= =可是为什么我的fft辣么慢!

    首先是很复杂的代换= =

    $$
    egin{align}
    c[k]
    = & sum_{k<=i<n} a[i]b[i-k] \
    = & sum_{0<=i-k<=n-k-1} a[i]b[i-k] \
    end{align}
    $$

    令$j=i-k, 则i=j+k$

    $$ c[k] =  sum_{0<=j<=n-k-1} a[j+k]b[j] $$

    设 $ c'[n-k-1]=c[k] , T=n-k-1 Rightarrow k=n-1-T $,有

    $$ c'[T] = sum_{0<=j<=T} a[n-1-(T-j)]b[j] $$

    最后再设 $ a'[T-j]=a[n-1-(T-j)] Rightarrow a'[x]=a[n-1-x] $

    然后就是裸的卷积辣= =

  • 相关阅读:
    011-iOS核心动画(Core Animation)
    010-CALayer(图层)
    009-手势触摸事件处理
    008-Quartz2D
    007-多控制器管理及其控制器间的数据传递
    007-多控制器管理(控制器间的数据传递)
    通过底层 socket 监控 http/https 思路
    NDK 线程同步
    时间同步算法探究
    Android 事件小结
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4279246.html
Copyright © 2020-2023  润新知