zoukankan      html  css  js  c++  java
  • BZOJ2194 快速傅立叶之二 【fft】

    题目

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

    输入格式

    第一行一个整数N,接下来N行,第i+2..i+N-1行,每行两个数,依次表示a[i],b[i] (0 < = i < N)。

    输出格式

    输出N行,每行一个整数,第i行输出C[i-1]。

    输入样例

    5

    3 1

    2 4

    1 1

    2 4

    1 4

    输出样例

    24

    12

    10

    6

    1

    题解

    和2179几乎一模一样
    由于卷积的定义要求下标之和为常数,我们尝试将原式变形,发现只要将a或者b反过来存就可以了

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<complex>
    #include<algorithm>
    #define pi acos(-1)
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 400005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
    	return out * flag;
    }
    typedef complex<double> E;
    E a[maxn],b[maxn];
    int n,m,L,R[maxn];
    void fft(E* a,int f){
    	for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);
    	for (int i = 1; i < n; i <<= 1){
    		E wn(cos(pi / i),f * sin(pi / i));
    		for (int j = 0; j < n; j += (i << 1)){
    			E w(1,0);
    			for (int k = 0; k < i; k++,w *= wn){
    				E x = a[j + k],y = w * a[j + k + i];
    				a[j + k] = x + y; a[j + k + i] = x - y;
    			}
    		}
    	}
    	if (f == -1) for (int i = 0; i < n; i++) a[i] /= n;
    }
    int main(){
    	n = read(); n--;
    	for (int i = 0; i <= n; i++){a[n - i] = read();b[i] = read();}
    	m = n << 1; for (n = 1; n <= m; n <<= 1) L++;
    	for (int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
    	fft(a,1); fft(b,1);
    	for (int i = 0; i <= n; i++) a[i] *= b[i];
    	fft(a,-1);
    	for (int i = (m >> 1); i >= 0; i--) printf("%d
    ",(int)(a[i].real() + 0.1));
    	return 0;
    }
    
    
  • 相关阅读:
    关于C++名字空间
    选择组合OR继承?
    编译器为C++ 空类自动生成的成员函数
    函数返回值为引用类型
    关于数据库存储过程分页DatagridView BindingNavigator 控件的详细实现
    ADO.NET 安全编码指南 来自MSDN
    ADO.NET中调用存储过程
    视图
    高效使用连接的模式
    GROUP BY, HAVING, COMPUTE, ORDER BY 语句
  • 原文地址:https://www.cnblogs.com/Mychael/p/8350641.html
Copyright © 2011-2022 走看看