zoukankan      html  css  js  c++  java
  • 【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] $

    然后就是裸的卷积辣= =

  • 相关阅读:
    ThinkPHP5如何引用新建的配置文件?
    MySQL与SQLServer的update left join语法区别
    如何POST一个JSON格式的数据给java接口,获得返回数据
    如何使用ThinkPHP5 ,自动生成目录?
    LeetCode347_TopK
    数据结构算法Review1_堆
    OJ_3_字符串数字相互转换
    C++Review11_指针数组和数组指针
    LeetCode15_三数之和
    LeetCode1_两数之和
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4279246.html
Copyright © 2011-2022 走看看