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 on the ground accidentally. Profess X wanted to check whether the device can still work properly. So he ran another n Hz sampling to the fallen device and got B0 ... Bn-1.

To compare two periodic signals, Profess X define the DIFFERENCE of signal A and B as follow:

You may assume that two signals are the same if their DIFFERENCE is small enough. 
Profess X is too busy to calculate this value. So the calculation is on you.

输入

The first line contains a single integer T, indicating the number of test cases.

In each test case, the first line contains an integer n. The second line contains n integers, A0 ... An-1. The third line contains n integers, B0 ... Bn-1.

T≤40 including several small test cases and no more than 4 large test cases.

For small test cases, 0<n≤6⋅103.

For large test cases, 0<n≤6⋅104.

For all test cases, 0≤Ai,Bi<220.

输出

For each test case, print the answer in a single line.

样例输入
2
9
3 0 1 4 1 5 9 2 6
5 3 5 8 9 7 9 3 2
5
1 2 3 4 5
2 3 4 5 1
样例输出
80
0
/*
hihocoder 1388 fft循环矩阵

problem:
给你两个数组,求差值平方和的最小值.  (a[i] - b[(i+k)%n])^

solve:
可以转换成 (a[i]*a[i]-2*a[i]*b[j]+b[j]*b[j]). 也就成了求a[i]*b[j]的最大值. 然后就没什么想法了- -
参考:http://blog.csdn.net/VictorZC8/article/details/52655099
说的是可以转换成两个数组相乘. 这样的话fft就能解决了. double型的话会有精度问题
结果发现别人是先求fft求完,比较出k的价值. 然后计算 ( 好机制Orz )

hhh-2016-09-25 16:53:25
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <math.h>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 1e6 + 1000;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const double eps = 1e-7;
template<class T> void read(T&num)
{
    char CH;
    bool F=false;
    for(CH=getchar(); CH<‘0‘||CH>‘9‘; F= CH==‘-‘,CH=getchar());
    for(num=0; CH>=‘0‘&&CH<=‘9‘; num=num*10+CH-‘0‘,CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
    if(!p)
    {
        puts("0");
        return;
    }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + ‘0‘);
    putchar(‘\n‘);
}

const double PI = acos(-1.0);

struct Complex
{
    double x,y;
    Complex(double _x = 0.0,double _y = 0.0)
    {
        x = _x;
        y = _y;
    }
    Complex operator-(const Complex &b)const
    {
        return Complex(x-b.x,y-b.y);
    }
    Complex operator+(const Complex &b)const
    {
        return Complex(x+b.x,y+b.y);
    }
    Complex operator*(const Complex &b)const
    {
        return Complex(x*b.x-y*b.y,x*b.y+y*b.x);
    }
};

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;
    }
}

Complex a[maxn];
Complex b[maxn];
ll x[maxn],y[maxn];
int n;

void File()
{
    freopen("in.txt","r",stdin);
}

int main()
{
    int T;
//    File();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int len = 1;
        while(len <= (n*2 -1)) len <<= 1;
        for(int i = 0;i < n;i++)
        {
            scanf("%lld",&x[i]);
            a[i] = x[i];
        }
        for(int i = n;i < len;i++)
            a[i] = 0;
        for(int i = 0;i < n;i++)
        {
            scanf("%lld",&y[i]);
        }
        for(int i = 0;i < n;i++) b[i] = y[n-1-i];
        for(int i = 0;i < n-1;i++) b[i+n] = y[n-1-i];
        for(int i = 2*n-1;i < len;i ++)
            b[i] = 0;
        fft(a,len,1);
        fft(b,len,1);

        for(int i = 0;i < len;i++)
            a[i] = a[i] * b[i];

        fft(a,len,-1);
        ll Max = -1;
        int pos = 0;
        for(int i = n-1,j = 0;j <= n;j++ )
        {
            if( (ll)(a[i+j].x + 0.5) > Max)
            {
                pos = j;
                Max = (ll)(a[i+j].x + 0.5);
            }
        }
        ll ans = 0;
        pos = (n-pos) % n;
//        cout << pos<<endl;

        for(int i = 0;i < n;i++)
        {
            ans += (x[i] - y[(i + pos) % n])*(x[i] - y[(i + pos) % n]);
        }
        print(ans);
    }
    return 0;
}

  

时间: 2024-08-07 17:02:29

hihocoder 1388 fft循环矩阵的相关文章

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

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

关于循环矩阵的一些理解和应用

问题引入 给定一个长度为\(n\)的环,每次对于一个位置上的数,加上它左边的数乘上\(L\),再加上右边的数乘上\(R\).\(L,R\)是给定的常数,问执行\(s\)次之后,这个环上的每个位置上的数是多少 (计算时左边和右边的数都是上一次的数) 如果\(n \leq 100, s \leq 2^{30}\) 可以想到矩阵快速幂 构造矩阵 \[ \begin{aligned} &\begin{bmatrix}a_1 & a_2 & \cdots & a_n\end{bmat

LA 3704细胞自动机——循环矩阵&amp;&amp;矩阵快速幂

题目 一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 \sim m-1$.给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m$ 的余数.给出 $n, m, d, k$ 和自动机各个格子的初始值.你的任务是计算 $k$ 次操作以后各格子的值.($1 \leq n\leq 500, 1 \leq m\leq 10^6, 0 \leq d\leq n/2, 1\leq k\leq 10^7$). 分析 如果我们把 $t$ 次操

UVA 1386 - Cellular Automaton(循环矩阵)

UVA 1386 - Cellular Automaton 题目链接 题意:给定一个n格的环,现在有个距离d,每次变化把环和他周围距离d以内的格子相加,结果mod m,问经过k次变换之后,环上的各个数字 思路:矩阵很好想,每个位置对应周围几个位置为1,其余位置为0,但是这个矩阵有500,有点大,直接n^3去求矩阵不太合适,然后观察发现这个矩阵是个循环矩阵,循环矩阵相乘的话,只需要保存一行即可,然后用n^2的时间就足够计算了 代码: #include <stdio.h> #include <

弱题(循环矩阵1)

问题 D: 弱题 时间限制: 1 Sec  内存限制: 128 MB提交: 46  解决: 28[提交][状态][讨论版] 题目描述 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为k(k < N),则将它重新标号为k + 1:若这个球标号为N,则将其重标号为1.(取出球后并不将其丢弃) 现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数. 输入 第1

POJ3150—Cellular Automaton(循环矩阵)

题目链接:http://poj.org/problem?id=3150 题目意思:有n个数围成一个环,现在有一种变换,将所有距离第i(1<=i<=n)个数小于等于d的数加起来,对m取余,现在要求将所有的数都变换k次,得到的n个数的值. 思路:构造一个循环矩阵,以下这个矩阵是以样例1为例的循环矩阵. 1 1 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 0 1 1 我们发现n尽然达到了500,复杂度是n^3logk,过不了,我们发现这个矩阵长得很奇葩,每一行都是

FZU Problem 1692 Key problem(循环矩阵)

循环矩阵,这里有解说:http://wenku.baidu.com/link? url=zcJ-sxrj0QDqzz8xCnHTnB7gxjoNRyOZzS4_4ZA22c8Bs9inYn6vVkqTVr_w-riLa8oRnYA9SRcCZ9f4UciCUNGeNAG4dCGclYRPS18YLGa 推出第一层以下依据性质就能够得到. Problem 1692 Key problem Accept: 144    Submit: 663 Time Limit: 1000 mSec    Mem