bzoj 4827 礼物

题目大意:

两个环之间的差异度定义为$\sum_{i=1}^n (a_i-b_i)^2$

可以进行两种操作 对其中一个环加上$c,m \geq c \geq 0$与对环进行旋转

思路:

对其中一个环加上非负整数相当于对于一个环加$c,c\in[-m,m]$

则设a环转了$j$,则差异度为$\sum_{i=1}^n (a_{i+j}+c-b_i)^2$

$\sum_{i=1}^n ({a_i}^2+{b_i}^2+c^2+2*c*(a_i-b_i)-2*a_{i+j}*b_i)$

由于$c$的范围很小,枚举$c$后除了最后一项都是可以可以快速算出来的

发现对于每一个$j$,$a$与$b$的下标之差为$j$考虑把其中一个数组倒序

则转化为卷积形式 使用$fft$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 200100
15 #define MOD 998244353
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (a+b)%MOD
21 #define mns(a,b) (a-b+MOD)%MOD
22 #define mul(a,b) (1LL*(a)*(b))%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,m,rev[MAXN],l2[MAXN],a1[MAXN],a2[MAXN];
32 const db pi=acos(-1);db sum,ans=inf;
33 struct Cd{db x,y;Cd(db X=0,db Y=0) {x=X,y=Y;}}a[MAXN],b[MAXN];
34 Cd operator + (Cd a,Cd b) {return (Cd){a.x+b.x,a.y+b.y};}
35 Cd operator - (Cd a,Cd b) {return (Cd){a.x-b.x,a.y-b.y};}
36 Cd operator * (Cd a,Cd b) {return (Cd){a.x*b.x-a.y*b.y,a.y*b.x+a.x*b.y};}
37 int q_pow(int x,int t,int res=1)
38 {
39     for(;t;t>>=1,x=mul(x,x))
40         if(t&1) res=mul(res,x);
41 }
42 void fft(Cd *a,int n,int f)
43 {
44     rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
45     for(int i=1;i<n;i<<=1)
46     {
47         Cd wn(cos(pi/i),f*sin(pi/i));
48         for(int j=0;j<n;j+=i<<1)
49         {
50             Cd w(1,0),x,y;
51             for(int k=0;k<i;k++,w=w*wn)
52                 x=a[k+j],y=a[i+k+j]*w,a[k+j]=x+y,a[i+k+j]=x-y;
53         }
54     }
55     if(f==1) return ;rep(i,0,n-1) a[i].x/=(db)n;
56 }
57 void solve(Cd *a,Cd *b,int sum)
58 {
59     int t=l2[sum]+1,lmt=1<<t;
60     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(t-1));
61     fft(a,lmt,1);fft(b,lmt,1);rep(i,0,lmt-1) a[i]=a[i]*b[i];
62     fft(a,lmt,-1);
63 }
64 int main()
65 {
66     n=read(),m=read();int lmt,t;
67     rep(i,0,n-1) a1[i]=read();rep(i,0,n-1) a2[i]=read();
68     l2[0]=-1;rep(i,1,n<<2) l2[i]=l2[i>>1]+1;lmt=1<<l2[n<<1]+1;
69     rep(i,0,n-1) a[i].x=a1[i],sum+=a1[i]*a1[i]+a2[i]*a2[i],t+=2*(a1[i]-a2[i]);
70     rep(i,0,n-1) a[i+n].x=a[i].x,b[i].x=a2[n-1-i];
71     solve(a,b,n<<1);
72     rep(x,-m,m)    rep(i,n-1,2*n-1) ans=min(ans,sum-t*x+n*x*x-2*round(a[i].x));
73     printf("%.0lf\n",ans);
74 }
View Code

 

posted @ 2019-03-13 09:53  jack_yyc  阅读(99)  评论(0编辑  收藏  举报