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 }