1. 程式人生 > >洛谷P3723 禮物

洛谷P3723 禮物

class splay 題意 amp n) swap 常數 函數 sin

以前看到過,但是搞不倒。知道了算法之後就好搞了。

題意:給定兩個長為n的序列,你可以把某個序列全部加上某個數c,變成循環同構序列。

求你操作後的min∑(ai - bi)2

解:

設加上的數為c,那麽得到一個柿子:∑(ai - bi + c)2

拆開:∑ai2 + ∑bi2 - 2∑aibi + nc2 + 2c∑(ai - bi)

發現其中前兩項是常數不用管。第三項是卷積,後兩項是關於c的二次函數。

於是後兩項用二次函數的對稱軸直接搞出來。第三項構造函數卷積,看哪個位置的值最大即可。

具體來說,把a復制成兩倍,反轉b。然後卷積出來的第n ~ 2n項就是。

技術分享圖片
  1 #include <cstdio>
  2
#include <algorithm> 3 #include <cmath> 4 5 typedef long long LL; 6 const int N = 300010; 7 const double pi = 3.1415926535897932384626; 8 const LL INF = 0x3f3f3f3f3f3f3f3f; 9 10 struct cp { 11 double x, y; 12 cp(double X = 0, double Y = 0) { 13 x = X; 14 y = Y;
15 } 16 inline cp operator +(const cp &w) const { 17 return cp(x + w.x, y + w.y); 18 } 19 inline cp operator -(const cp &w) const { 20 return cp(x - w.x, y - w.y); 21 } 22 inline cp operator *(const cp &w) const { 23 return cp(x * w.x - y * w.y, x * w.y + y * w.x);
24 } 25 }a[N], b[N]; 26 27 int r[N]; 28 LL A[N], B[N]; 29 30 inline void FFT(int n, cp *a, int f) { 31 for(int i = 0; i < n; i++) { 32 if(i < r[i]) { 33 std::swap(a[i], a[r[i]]); 34 } 35 } 36 for(int len = 1; len < n; len <<= 1) { 37 cp Wn(cos(pi / len), f * sin(pi / len)); 38 for(int i = 0; i < n; i += (len << 1)) { 39 cp w(1, 0); 40 for(int j = 0; j < len; j++) { 41 cp t = a[i + len + j] * w; 42 a[i + len + j] = a[i + j] - t; 43 a[i + j] = a[i + j] + t; 44 w = w * Wn; 45 } 46 } 47 } 48 if(f == -1) { 49 for(int i = 0; i <= n; i++) { 50 a[i].x /= n; 51 } 52 } 53 return; 54 } 55 56 int main() { 57 int n, m; 58 LL XX = 0, YY = 0, SX = 0, SY = 0; 59 scanf("%d%d", &n, &m); 60 n--; 61 for(int i = 0; i <= n; i++) { 62 scanf("%lld", &A[i]); 63 SX += A[i]; 64 XX += A[i] * A[i]; 65 a[i].x = a[i + n + 1].x = A[i]; 66 } 67 for(int i = 0; i <= n; i++) { 68 scanf("%lld", &B[i]); 69 SY += B[i]; 70 YY += B[i] * B[i]; 71 b[n - i].x = B[i]; 72 } 73 int len = 2, lm = 1; 74 while(len <= n * 3) { 75 len <<= 1; 76 lm++; 77 } 78 for(int i = 1; i <= len; i++) { 79 r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1)); 80 } 81 82 FFT(len, a, 1); 83 FFT(len, b, 1); 84 for(int i = 0; i <= len; i++) { 85 a[i] = a[i] * b[i]; 86 } 87 FFT(len, a, -1); 88 89 LL ans = -INF; 90 for(int i = n; i <= n * 2; i++) { 91 ans = std::max(ans, (LL)(a[i].x + 0.5)); 92 } 93 94 double C = -1.0 * (SX - SY) / (n + 1); 95 LL c = (int)(C); 96 LL temp = std::min((n + 1) * c * c + 2 * (SX - SY) * c, (n + 1) * (c + 1) * (c + 1) + 2 * (SX - SY) * (c + 1)); 97 temp = std::min(temp, (n + 1) * (c - 1) * (c - 1) + 2 * (SX - SY) * (c - 1)); 98 99 printf("%lld\n", XX + YY - 2 * ans + temp); 100 101 return 0; 102 }
AC代碼

洛谷P3723 禮物