• bzoj2194「快速傅立叶之二」


    bzoj2194「快速傅立叶之二」

    题目描述

    请计算

    [c[k]=sum_{i=0}^{n-1} a[i] imes b[i-k];(kleq i < n) ]

    输入格式

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

    输出格式

    输出 (n) 行,每行一个整数,第 (i) 行输出 (c[i-1])

    样例

    样例输入

    5
    3 1
    2 4
    1 1
    2 4
    1 4
    

    样例输出

    24
    12
    10
    6
    1
    

    数据范围

    (nleq 1e5,0 leq a[i],b[i]leq 100,a[i],b[i]in mathbb{Z})

    题解

    一个比较常见的套路:将某个数组 (reverse) 一下,形成卷积的形式。

    比如这个题,我们将 (a) 数组 (reverse),原始变成了

    [c[k]=sum_{i=0}^{n-1} a[n-i] imes b[i-k] ]

    很容易发现这是一个卷积的形式

    [c[n-k]=sum_{i+j=n-k} a[i] imes b[j] ]

    最后用 (FFT)(NTT) 解决都可。

    代码
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int maxn = 3e5 + 50, INF = 0x3f3f3f3f;
    const double pi = acos (- 1.0);
    
    inline int read () {
    	register int x = 0, w = 1;
    	register char ch = getchar ();
    	for (; ch < '0' || ch > '9'; ch = getchar ()) if (ch == '-') w = -1;
    	for (; ch >= '0' && ch <= '9'; ch = getchar ()) x = x * 10 + ch - '0';
    	return x * w;
    }
    
    inline void write (register int x) {
    	if (x / 10) write (x / 10);
    	putchar (x % 10 + '0');
    }
    
    int n, bit, len = 1, rev[maxn];
    
    struct Complex {
    	double x, y;
    	Complex () { x = y = 0; }
    	Complex (register double a, register double b) { x = a, y = b; }
    	inline Complex operator + (const Complex &a) const { return Complex (x + a.x, y + a.y); }
    	inline Complex operator - (const Complex &a) const { return Complex (x - a.x, y - a.y); }
    	inline Complex operator * (const Complex &a) const { return Complex (x * a.y + y * a.x, y * a.y - x * a.x); }
    } a[maxn], b[maxn];
    
    inline void FFT (register int len, register Complex *a, register int opt) {
    	for (register int i = 0; i < len; i ++) if (i < rev[i]) swap (a[i], a[rev[i]]);
    	for (register int d = 1; d < len; d <<= 1) {
    		register Complex w1 = Complex (opt * sin (pi / d), cos (pi / d));
    		for (register int i = 0; i < len; i += d << 1) {
    			register Complex w = Complex (0, 1);
    			for (register int j = 0; j < d; j ++, w = w * w1) {
    				register Complex x = a[i + j], y = w * a[i + j + d];
    				a[i + j] = x + y, a[i + j + d] = x - y;
    			}
    		}
    	}
    }
    
    int main () {
    	n = read();
    	for (register int i = 0; i < n; i ++) a[i].y = read(), b[i].y = read();
    	reverse (a, a + n + 1);
    	while (len <= n << 1) len <<= 1, bit ++;
    	for (register int i = 1; i < len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
    	FFT (len, a, 1), FFT (len, b, 1);
    	for (register int i = 0; i < len; i ++) a[i] = a[i] * b[i];
    	FFT (len, a, -1);
    	for (register int i = n; i > 0; i --) printf ("%d
    ", (int) (0.5 + a[i].y / len));
    	return 0;
    }
    
  • 相关阅读:
    [django]自定义标签和过滤器
    [js]js中6种错误处理机制
    [js] Array.slice和类数组转数组
    [js]this和call.call
    [py]python的time和datetime模块获取星期几
    CentOS 普通用户提升root权限
    CentOS ACL
    CentOS 文件隐藏属性
    CentOS 文件特殊权限SUID,SGID,SBIT
    CentOS 用户管理useradd、usermod等
  • 原文地址:https://www.cnblogs.com/Rubyonly233/p/14214582.html
Copyright © 2020-2023  润新知