hihoCoder 1388(fft)

让你求(a[i] - b[(i + x) % n]) ^ 2的最大值,其中x从0到n-1。

因为结果总是sum(a[i] ^ 2) + sum(b[i] ^ 2) - sum(2 * a[i] * b[(i + x) % n])。

因此只需要找到最小的sum(2 * a[i] * b[(i + x) % n])即可。

据此我们构造两个向量。

a = (a[n - 1], a[n - 2], ... , a[1], a[0], a[n - 1], a[n - 2], ... , a[2], a[1])

b = (b[0], b[1], ... , b[n - 2], b[n - 1])

可以看出要求sum的最小值就是求ab的卷积从n-1到2 * n - 2的最小值(下标从0开始)。

因此用fft可以求出卷积,再找一遍最小值,记住偏移量,根据偏移量计算结果就ok

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
const int maxn = 240005;
const double PI = acos(-1.0);
struct Complex
{
    double x, y;
    Complex(double x = 0, double y = 0) : x(x), y(y) { }
    Complex operator + (const Complex &rhs)
    {
        return Complex(x + rhs.x, y + rhs.y);
    }
    Complex operator - (const Complex &rhs)
    {
        return Complex(x - rhs.x, y - rhs.y);
    }
    Complex operator * (const Complex &rhs)
    {
        return Complex(x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x);
    }
}a[maxn], b[maxn];
long long num1[maxn], num2[maxn];
void change(Complex y[], int len)
{
    int i, j, k;
    for(i = 1, j = len / 2; i < len - 1; ++i)
    {
        if(i < j)
            swap(y[i], y[j]);
        k = len / 2;
        while(j >= k)
        {
            j -= k;
            k /= 2;
        }
        if(j < k)
            j += k;
    }
}
void fft(Complex y[], int len, int on)
{
    change(y, len);
    for(int h = 2; h <= len; h <<= 1)
    {
        Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
        for(int j = 0; j < len; j += h)
        {
            Complex w(1, 0);
            for(int k = j; k < j + h / 2; ++k)
            {
                Complex u = y[k];
                Complex t = w * y[k + h / 2];
                y[k] = u + t;
                y[k + h / 2] = u - t;
                w = w * wn;
            }
        }
    }
    if(on == -1)
        for(int i = 0; i < len; ++i)
            y[i].x /= len;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%lld", &num1[i]);
            a[n - i - 1].x = num1[i];
            a[n - i - 1].y = 0;
        }
        for(int i = n; i < 2 * n - 1; ++i)
        {
            a[i].x = a[i - n].x;
            a[i].y = 0;
        }
        for(int i = 0; i < n; ++i)
        {
            scanf("%lld", &num2[i]);
            b[i].x = num2[i];
            b[i].y = 0;
        }
        int tmp = 1;
        while(tmp < 2 * n - 1) tmp <<= 1;
        for(int i = 2 * n - 1; i < tmp; ++i)
        {
            a[i].x = a[i].y = 0;
        }
        for(int i = n; i < tmp; ++i)
        {
            b[i].x = b[i].y = 0;
        }
        fft(a, tmp, 1);
        fft(b, tmp, 1);
        for(int i = 0; i < tmp; ++i)
            a[i] = a[i] * b[i];
        fft(a, tmp, -1);
        double MAX = -1;
        int pos = -1;
        for(int i = n - 1; i < 2 * n - 1; ++i)
        {
            if(a[i].x > MAX)
            {
                MAX = a[i].x;
                pos = i;
            }
        }
        pos = pos - n + 1;
        long long ans = 0;
        for(int i = 0; i < n; ++i)
        {
            ans += (num1[i] - num2[(i + pos) % n]) * (num1[i] - num2[(i + pos) % n]);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

时间: 2024-10-13 18:47:07

hihoCoder 1388(fft)的相关文章

hihocoder 1388 fft循环矩阵

#1388 : Periodic Signal 时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device which can send a particular 1 second signal repeatedly. The signal is A0 ... An-1 under n Hz sampling. One day, the device fell

hihocoder #1388 : Periodic Signal NTT&amp;FFT

传送门:hihocoder #1388 : Periodic Signal 先来几个大牛传送门:  (模板) NTT long long 版 解法一:因为我们知道FFT会精度不够,所以坚持用NTT,但是模数不够大,然后就一直GG,看来我们的搜索姿势也有问题,居然没有搜到上面大神的板子,真的是GG http://www.cnblogs.com/WABoss/p/5903927.html /*******************************************************

hihocoder 1388 Periodic Signal

Periodic Signal 时间限制:5000ms 单点时限:5000ms 内存限制:256MB Description Profess X is an expert in signal processing. He has a device which can send a particular 1 second signal repeatedly. The signal is A0 ... An-1 under n Hz sampling. One day, the device fel

hihoCoder 1388 Periodic Signal(FFT)

[题目链接] http://hihocoder.com/problemset/problem/1388 [题目大意] 给出A数列和B数列,求下图式子: [题解] 我们将多项式拆开,我们可以得到固定项A2和B2,以及变动项-2AB,所以现在只要最大化AB即可.我们发现将A序列倒置,B序列倍置,所得到的卷积序列中的最大值就是AB的最大值,但是考虑到精度问题,我们在所得到的卷积序列中只判断极值产生的位置而不是直接获得极值,最后我们从极值产生的位置直接计算答案即可. [代码] #include <cst

hihoCoder #1388 : Periodic Signal ( 2016 acm 北京网络赛 F题)

时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device which can send a particular 1 second signal repeatedly. The signal is A0 ... An-1 under n Hz sampling. One day, the device fell on the ground accidenta

XJTUOJ wmq的A&#215;B Problem FFT

wmq的A×B Problem 发布时间: 2017年4月9日 17:06   最后更新: 2017年4月9日 17:07   时间限制: 3000ms   内存限制: 512M 描述 这是一个非常简单的问题. wmq如今开始学习乘法了!他为了训练自己的乘法计算能力,写出了n个整数,并且对每两个数a,b都求出了它们的乘积a×b.现在他想知道,在求出的n(n−1)2个乘积中,除以给定的质数m余数为k(0≤k<m)的有多少个. 输入 第一行为测试数据的组数. 对于每组测试数据,第一行为2个正整数n,

对AM信号FFT的matlab仿真

普通调幅波AM的频谱,大信号包络检波频谱分析 u(t)=Ucm(1+macos ?t)cos ?ct ma称为调幅系数 它的频谱由载波,上下边频组成 , 包络检波中二极管截去负半周再用电容低通滤波,可以得到基带信号,那么,截去负半周后的AM信号必定包含基带信号的频谱.我们可以通过matlab来验证. %已知基带信号为1hz,载波为64hz,调制系数ma=0.3,采样频率1024hz,FFT变换区间N为2048 clear; fs=1024; f=1; %1hz基带信号 fc=64; %64hz载

[hihoCoder#1381]Little Y&#39;s Tree

[hihoCoder#1381]Little Y's Tree 试题描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每次小J会删掉这个树中的k条边,这棵树被分成k+1个连通块.小J想知道每个连通块中最远点对距离的和. 这里的询问是互相独立的,即每次都是在小Y的原树上进行操作. 输入 第一行一个整数n,接下来n-1行每行三个整数u,v,w,其中第i行表示第i条边边权为wi,连接了ui,vi两点. 接下来一行一个整数q,表示有q组询问. 对于每组询问,第一行一个正整数k,接下来一

多项式FFT相关模板

自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <algorithm> #include <vector> using namespace std; #de