Periodic Signal BeiJing 2016 区域赛

来源:互联网 发布:浮雕设计软件 编辑:程序博客网 时间:2024/05/21 20:29

Problem:

当k为多少时式子的值最小。
Solution:
整理后可知,A2i+B2i2AiBi+k前面是固定的,相当于求后面的最小值,形式上类似卷积,但是我们为了把k求出来,那么我们可以翻转A,这样差值恰好为k

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 262144const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1//const int P=1004535809; // 479 * 2 ^ 21 + 1//const int P=998244353; // 119 * 2 ^ 23 + 1const int G=3;long long mul(long long x,long long y){    return (x*y-(long long)(x/(long double)P*y+1e-3)*P+P)%P;}long long qpow(long long x,long long k,long long p){    long long ret=1;    while(k){        if(k&1) ret=mul(ret,x);        k>>=1;        x=mul(x,x);    }    return ret;}long long wn[25];void getwn(){    for(int i=1; i<=18; ++i){        int t=1<<i;        wn[i]=qpow(G,(P-1)/t,P);    }}int len;void NTT(long long y[],int op){    for(int i=1,j=len>>1,k; i<len-1; ++i){        if(i<j) swap(y[i],y[j]);        k=len>>1;        while(j>=k){            j-=k;            k>>=1;        }        if(j<k) j+=k;    }    int id=0;    for(int h=2; h<=len; h<<=1) {        ++id;        for(int i=0; i<len; i+=h){            long long w=1;            for(int j=i; j<i+(h>>1); ++j){                long long u=y[j],t=mul(y[j+h/2],w);                y[j]=u+t;                if(y[j]>=P) y[j]-=P;                y[j+h/2]=u-t+P;                if(y[j+h/2]>=P) y[j+h/2]-=P;                w=mul(w,wn[id]);            }        }    }    if(op==-1){        for(int i=1; i<len/2; ++i) swap(y[i],y[len-i]);        long long inv=qpow(len,P-2,P);        for(int i=0; i<len; ++i) y[i]=mul(y[i],inv);    }}void Convolution(long long A[],long long B[],int n){    for(len=1; len<(n<<1); len<<=1);    for(int i=n; i<len; ++i){        A[i]=B[i]=0;    }    NTT(A,1); NTT(B,1);    for(int i=0; i<len; ++i){        A[i]=mul(A[i],B[i]);    }    NTT(A,-1);}long long A[MAXN],B[MAXN];int main(){    getwn();    int t,n;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        long long ans=0;        for(int i=0; i<n; ++i){            scanf("%lld",&A[i]);            ans+=A[i]*A[i];        }        for(int i=0; i<n; ++i){            scanf("%lld",&B[n-i-1]);            ans+=B[n-i-1]*B[n-i-1];        }        for(int i=0; i<n; ++i){            A[i+n]=A[i];            B[i+n]=0;        }        Convolution(A,B,2*n);        long long mx=0;        for(int i=n; i<2*n; ++i){            mx=max(mx,A[i]);        }        printf("%lld\n",ans-2*mx);    }    return 0;}
1 0
原创粉丝点击