zoukankan      html  css  js  c++  java
  • bzoj 4827: [HNOI2017]礼物 (FFT)

    一道FFT

    然而据说暴力可以水70分

    然而我省选的时候看到了直接吓傻了  连暴力都没打

    太弱了啊QAQ

    emmmm

    详细的拆开就看其他题解吧233

    最后那一步卷积其实我一直没明白

    后来画画图终于懂了

    只要把其中一个反过来

    多项式乘法的结果中的每一项系数就对应某一个Σx[i] * y[j] 的结果

    前面几项是不完全的结果

    但是太小了就被忽略啦

    代码如下

    /**************************************************************
        Problem: 4827
        User: cminus
        Language: C++
        Result: Accepted
        Time:5644 ms
        Memory:24568 kb
    ****************************************************************/
     
    #include <cstdio>
    #include <cmath>
    #include <complex>
    using namespace std;
     
    const int N = 500100;
    typedef long long ll;
    typedef complex<double> cp;
    const double pi = acos(-1.0);
    cp A[N], B[N];
     
    void FFT(cp *y, int n, int type) {
        if (n == 1) return ;
        cp l[n >> 1], r[n >> 1];
        for (int i = 0; i <= n; i++)
            if (i & 1)  r[i >> 1] = y[i];
            else    l[i >> 1] = y[i];
        FFT(l, n >> 1, type); FFT(r, n >> 1, type);
        cp omegan(cos(2 * pi / n), sin(2 * pi * type / n)), omega(1, 0);
        for (int i = 0; i < n >> 1; i++) {
            y[i] = l[i] + r[i] * omega;
            y[i + (n >> 1)] = l[i] - r[i] * omega;
            omega *= omegan;
        }
    }
     
    int main() {
        int n, m, ans = 0, y = 0;
        scanf("%d %d", &n, &m);
        for (int i = 0; i < n; i++) {
            int x; scanf("%d", &x);
            A[n - i - 1] = x;
            ans += x * x;
        }
        for (int i = 0; i < n; i++) {
            int x; scanf("%d", &x);
            B[i] = x;
            ans += x * x;
            y += (int)B[i].real() - A[n - i - 1].real();
        }
        int n1;  for (n1 = 1; n1 <= n * 4; n1 <<= 1);
        for (int i = 0; i < n; i++)
            B[i + n] = B[i];
        FFT(A, n1, 1); FFT(B, n1, 1);
        for (int i = 0; i <= n1; i++)
            A[i] *= B[i];   
        FFT(A, n1, -1);
        int temp = 0, z = (-y) / n;
        for (int i = 0; i < n; i++)  temp = max(temp, (int)(A[i + n - 1].real() / n1 + 0.5));
        ans -= temp * 2;
        temp = z * z * n + y * z * 2;
        z += 1; temp = min(temp, z * z * n + y * z * 2);
        z -= 2; temp = min(temp, z * z * n + y * z * 2);
    // 有理有据的精度优化
        ans += temp;
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    Mysql 5.6 源码编译安装
    Python中的数据类型之字符串
    Python中变量的命名与使用(个人总结)
    Windows环境下python3.7版本怎么安装pygame
    web应用无法访问的原因之一以及如何设置数据库编码
    项目代码设计规范总结之分页查询
    当java web项目部署到服务器上时,无法将图片等媒体文件保存到服务器的最终奥义
    如何查看服务器上打印的信息
    java代码实现JVM栈溢出,堆溢出
    springmvc源码分析(转)
  • 原文地址:https://www.cnblogs.com/cminus/p/7398313.html
Copyright © 2011-2022 走看看