题解 P3723 【[AH2017/HNOI2017]礼物】

panda_2134

2018-03-11 12:48:04

Solution

(这应该是步骤最全的题解了233) 考虑到公式可能出问题,我就贴图片好了 (洛谷图床压了图,重新传一次) ------------------- ## 推导过程 ![Formula](https://raw.githubusercontent.com/panda2134/panda2134.github.io/master/img/Gift.png) ## 代码 ```cpp #include <bits/stdc++.h> #define PI M_PI using namespace std; typedef long long int64; typedef std::complex<double> cmplx; const int MAXN = 4e5; namespace FFT { inline cmplx get_rt(int step, bool inv) { return !inv ? cmplx(cos(2*PI / step), sin(2*PI / step)) : cmplx(cos(2*PI / step), -sin(2*PI / step)); } void fft(int len, cmplx* A, bool inv) { static int R[MAXN+10]; for(int i = 1; i < len; i++) R[i] = ((R[i>>1]>>1) | (len>>(i&1))) & (len-1); for(int i = 0; i < len; i++) if(R[i] > i) swap(A[i], A[R[i]]); for(int step = 1; step < len; step <<= 1) for(int i = 0; i < len; i += (step<<1)) { cmplx omega = 1, rt = get_rt(step<<1, inv); for(int j = 0; j < step; j++, omega *= rt) { cmplx t = omega * A[i+j+step]; A[i+j+step] = A[i+j] - t; A[i+j] = A[i+j] + t; } } if(inv) for(int i = 0; i < len; i++) A[i] /= len; } void conv(int64* A, int64* B, int64* C, int deg) { static cmplx CA[MAXN+10], CB[MAXN+10], CC[MAXN+10]; int len; for(len = 1; len <= ((deg + 1) << 1); len <<= 1); fill(CA, CA + len, 0); fill(CB, CB + len, 0); fill(CC, CC + len, 0); for(int i = 0; i <= deg; i++) { CA[i] = A[i], CB[i] = B[i]; } fft(len, CA, false); fft(len, CB, false); for(int i = 0; i < len; i++) CC[i] = CA[i] * CB[i]; fft(len, CC, true); for(int i = 0; i < len; i++) C[i] = int64(real(CC[i]) + 0.5); } } using FFT::conv; int64 n, m, SumY, SumY2, SumC, SumC2, C[MAXN+10], Y[MAXN+10], T[MAXN+10]; inline int readint() { int f=1, r=0; char c=getchar(); while(!isdigit(c)) { if(c=='-')f=-1; c=getchar(); } while(isdigit(c)) { r=r*10+c-'0'; c=getchar(); } return f*r; } void Init() { n = readint(); m = readint(); for(int i = 0; i < n; i++) C[i] = C[i+n] = readint(); for(int i = 1; i <= n; i++) Y[i] = readint(); reverse(C, C+n); reverse(C+n, C+2*n); conv(C, Y, T, 2*n); for(int i = 1; i <= n; i++) { SumY += Y[i]; SumY2 += Y[i] * Y[i]; } for(int i = 0; i < n; i++) { SumC += C[i]; SumC2 += C[i] * C[i]; } } void Work() { int64 Ans = LLONG_MAX; for(int a = 0; a <= n-1; a++) { int64 CurP, CurAns = LLONG_MAX, CoeA, CoeB, CoeC; CoeA = n; CoeB = 2*SumC - 2*SumY; CoeC = SumY2 + SumC2 - 2*T[n + a]; CurP = (-CoeB) / (2*CoeA); for(int P = max(-m, CurP - 10); P <= min(m, CurP + 10); ++P) CurAns = min(CurAns, CoeA * P * P + CoeB * P + CoeC); Ans = min(Ans, CurAns); } cout << Ans; } int main() { Init(); Work(); return 0; } ```