zoukankan      html  css  js  c++  java
  • [AH2017/HNOI2017]礼物

    嘟嘟嘟


    感觉fft的题重点在于推式子……


    因为(n leqslant 5e4, m leqslant 100),所以可以枚举旋转的位置和增加的亮度,然后想办法在(O(1))时间内得到答案。
    令枚举到第(i)个位置时(A, B)两个手环的序列为(A_i, B_i),此时(B_i)整体怎加了(x)亮度,则:

    [ans = sum_{i = 0} ^ {n - 1} (a_i - b_i - x) ^ 2 ]

    然后拆开((a_i - b_i - x) ^ 2)
    ({a_i} ^ 2 + {b_i} ^ 2 + x ^ 2 - 2a_i b_i - 2a_i x + 2b_i x).
    于是

    [ans = sum_{i = 0} ^ {n - 1} {a_i} ^ 2 + sum_{i = 0} ^ {n - 1} {b_i} ^ 2 + nx ^ 2 - 2x(sum_{i = 0} ^ {n - 1} b_i - sum_{i = 0} ^ {n - 1} a_i) - 2 sum_{i = 0} ^ {n - 1} a_i b_i ]

    然后就发现只有最后一项是不知道的,而且只要把(A)翻转一下,就可以卷积了!
    但是如果在每一次枚举都求一遍卷积,(O(mn ^ 2 log{n}))时间肯定撑不住,而且求的时候也有很多重复的部分。
    因此,我们可以断环为链,得到一个翻转后的长度为(2n)(A)的序列。然后和(B)卷积。
    枚举到第(i)个位置的时候,根据卷积下标相加,(c(n + i))就是答案。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define rg register
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 8e6 + 5;
    const db PI = acos(-1);
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    int n, m, len = 1;
    ll a2 = 0, b2 = 0, suma = 0, sumb = 0;
    ll Max = 0, ans = INF;
    
    struct Comp
    {
      db x, y;
      inline Comp operator + (const Comp& oth)const
      {
        return (Comp){x + oth.x, y + oth.y};
      }
      inline Comp operator - (const Comp& oth)const
      {
        return (Comp){x - oth.x, y - oth.y};
      }
      inline Comp operator * (const Comp& oth)const
      {
        return (Comp){x * oth.x - y * oth.y, x * oth.y + oth.x * y};
      }
      inline friend void swap(Comp& a, Comp& b)
      {
        swap(a.x, b.x); swap(a.y, b.y);
      }
    }a[maxn], b[maxn], omg[maxn], inv[maxn];
    void init()
    {
      omg[0] = inv[0] = (Comp){1, 0};
      omg[1] = inv[len - 1] = (Comp){cos(2 * PI / len), sin(2 * PI / len)};
      for(int i = 2; i < len; ++i) omg[i] = inv[len - i] = omg[i - 1] * omg[1];
    }
    void fft(Comp* a, Comp* omg)
    {
      int lim = 0;
      while((1 << lim) < len) lim++;
      for(int i = 0; i < len; ++i)
        {
          int t = 0;
          for(int j = 0; j < lim; ++j) if((i >> j) & 1) t |= (1 << (lim - j - 1));
          if(i < t) swap(a[i], a[t]);
        }
      for(int l = 2; l <= len; l <<= 1)
        {
          int q = l >> 1;
          for(Comp* p = a; p != a + len; p += l)
    	for(int i = 0; i < q; ++i)
    	  {
    	    Comp t = omg[len / l * i] * p[i + q];
    	    p[i + q] = p[i] - t, p[i] = p[i] + t;
    	  }
        }
    }
    
    int main()
    {
      n = read(); m = read();
      for(int i = 0; i < n; ++i)
        {
          db x = read();
          a[i] = a[n + i] = (Comp){x, 0};
          a2 += x * x; suma += x;
        }
      for(int i = 0; i < n; ++i)
        {
          db x = read();
          b[n - i - 1] = (Comp){x, 0};
          b2 += x * x; sumb += x;
        }
      while(len < (n << 1) + n) len <<= 1;
      init();
      fft(a, omg); fft(b, omg);
      for(int i = 0; i < len; ++i) a[i] = a[i] * b[i];
      fft(a, inv);
      for(int i = 0; i < len; ++i) a[i].x = (ll)(a[i].x / len + 0.5);
      for(int i = 0; i < n; ++i)
        for(int j = -m; j <= m; ++j)
          ans = min(ans, a2 + b2 + (ll)n * j * j - (((sumb - suma) * j) << 1) - ((ll)a[i + n].x << 1));
      write(ans), enter;
      return 0;
    }
    
  • 相关阅读:
    CSS3 object-fit 图像裁剪
    jQuery.extend 使用函数
    ios 不支持iframe 解决方案
    详解HTML5中rel属性的prefetch预加载功能使用
    web页面加载、解析、渲染过程
    TCP的三次握手(建立连接)与 四次挥手(关闭连接)
    html---规范、细节积累-01
    pio设置单元格式
    让一个数字显示指定位数
    linux下获取微秒级精度的时间
  • 原文地址:https://www.cnblogs.com/mrclr/p/10096071.html
Copyright © 2011-2022 走看看