ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SPOJ - Triple Sums

2019-11-17 19:03:35  阅读:316  来源: 互联网

标签:const int double sum Sums SPOJ Complex Triple return


 

【传送门】

FFT第一题!

构造多项式 $A(x) = \sum x ^ {s_i}$。

不考虑题目中 $i < j < k$ 的条件,那么 $A^3(x)$ 每一项对应的系数就是答案了。

 考虑容斥。

$$(\sum x)^3 = \sum x^3 + 3 \sum x^2 y + 6\sum xyz$$

$$(\sum x^2) (\sum x)= \sum x^3 + \sum x^2 y$$

所以 $$\sum xyz = \dfrac{(\sum x)^3 - 3 (\sum x^2)(\sum x) + 2 \sum x^3}{6}$$ 

#include <bits/stdc++.h>

struct Complex {
    double r, i;
    Complex(double r = 0.0, double i = 0.0): r(r), i(i) {}
    Complex operator + (const Complex &p) const { return Complex(r + p.r, i + p.i); }
    Complex operator - (const Complex &p) const { return Complex(r - p.r, i - p.i); }
    Complex operator * (const Complex &p) const { return Complex(r * p.r - i * p.i, r * p.i + i * p.r); }
};

const double pi = acos(-1.0);
const int N = 2e5 + 7;
int n, limit, r[N], l;
int v[N], A[N], B[N], C[N];
Complex a[N], b[N], c[N];

void FFT(Complex *a, int pd) {
    for (int i = 0; i < limit; i++)
        if (i < r[i])
            std::swap(a[i], a[r[i]]);
    for (int mid = 1; mid < limit; mid <<= 1) {
        Complex wn = Complex(cos(pi / mid), pd * sin(pi / mid));
        for (int l = mid << 1, j = 0; j < limit; j += l) {
            Complex w = Complex(1.0, 0.0);
            for (int k = 0; k < mid; k++, w = w * wn) {
                Complex u = a[k + j], v = w * a[k + j + mid];
                a[k + j] = u + v;
                a[k + j + mid] = u - v;
            }
        }
    }
    if (pd == -1)
        for (int i = 0; i < limit; i++)
            a[i] = Complex(a[i].r / limit, a[i].i / limit);
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        x += 20000;
        A[x]++;
        B[x * 2]++;
        C[x * 3]++;
    }
    for (int i = 0; i <= 40000; i++)
        a[i] = Complex((double)A[i], 0.0);
    for (int i = 0; i <= 80000; i++)
        b[i] = Complex((double)B[i], 0.0);
    limit = 1;
    while (limit <= 40000 + 80000)
        limit <<= 1, l++;
    for (int i = 0; i < limit; i++)
        r[i] = r[i >> 1] >> 1 | ((i & 1) << (l - 1));
    FFT(a, 1);
    FFT(b, 1);
    for (int i = 0; i < limit; i++)
        b[i] = b[i] * a[i];
    for (int i = 0; i < limit; i++)
        a[i] = a[i] * a[i] * a[i];
    FFT(a, -1);
    FFT(b, -1);
    for (int i = 0; i <= 120000; i++) {
        long long ans = (long long)((a[i].r - 3.0 * b[i].r + 2.0 * C[i]) / 6.0 + 0.5);
        if (ans > 0)
            printf("%d : %lld\n", i - 60000, ans);
    }
    return 0;
}
View Code

 

标签:const,int,double,sum,Sums,SPOJ,Complex,Triple,return
来源: https://www.cnblogs.com/Mrzdtz220/p/11877508.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有