codeforces 632E FFT快速幂优化

来源:互联网 发布:九章算法bat班视频 编辑:程序博客网 时间:2024/06/01 21:35

简略题意:n种物品,每种物品有对应的权值,每种物品的数量没有限制。现在问取k个物品能够组成的权值有哪些。

假若只能取两个物品,就是一个很经典的生成函数问题,相当于做一次多项式乘法,可以用FFT去优化这个过程。现在我们做k次多项式乘法,就可以用快速幂去加速这个过程。
复杂度O(maxvklog(maxvlogk)log(k))

#include <bits/stdc++.h>using namespace std;typedef long long LL;const LL kMaxn = 4e6;typedef long double ld;const double kPi = acos(-1.0);int len, n;struct Complex {    double r, i;    Complex(double r = 0, double i = 0):r(r), i(i) {};    Complex operator + (const Complex & rhs) {        return Complex(r + rhs.r, i + rhs.i);    }    Complex operator - (const Complex & rhs) {        return Complex(r - rhs.r, i - rhs.i);    }    Complex operator * (const Complex &rhs) {        return Complex(r * rhs.r - i * rhs.i, i * rhs.r + r * rhs.i);    }} va[kMaxn], vb[kMaxn];void Rader(Complex F[], int len) {    int j = len >> 1;    for(int i = 1; i < len - 1; i++) {        if(i < j) swap(F[i], F[j]);        int k = len >> 1;        while(j >= k) {            j -= k;            k >>= 1;        }        if(j < k) j += k;    }}void FFT(Complex F[], int len, int t) { //时域转频域    Rader(F, len);    for(int h = 2; h <= len; h <<= 1) {        Complex wn(cos(-t*2*kPi/h), sin(-t*2*kPi/h));        for(int j = 0; j < len; j += h) {            Complex E(1, 0);            for(int k = j; k < j + h / 2; k++) {                Complex u = F[k];                Complex v = E*F[k+h/2];                F[k] = u + v;                F[k+h/2] = u - v;                E = E * wn;            }        }    }    if(t == -1) {        for(int i = 0; i < len; i++) {            F[i].r /= len;        }    }}void Init(int *a, int *b, int &v1, int v2) {    int n1 = v1, n2 = v2;    len = 1;    while(len < 2*n1 || len < 2*n2) len <<= 1;    int i;    for(i = 0; i < n1; i++)        va[i].r = a[i], va[i].i = 0;    while(i < len) va[i].r = va[i].i = 0, i++;    for(i = 0; i < n2; i++)        vb[i].r = b[i], vb[i].i = 0;    while(i < len) vb[i].r = vb[i].i = 0, i++;    v1 += v2;}void Solve(int *a, int *b, int &v1, int v2) {    Init(a, b, v1, v2);    FFT(va, len, 1);    FFT(vb, len, 1);    for(int i = 0; i < len; i++) va[i] = va[i] * vb[i];    FFT(va, len, -1);    for(int i = 0; i < len; i++)        a[i] = (int)(va[i].r + 0.5)?1:0;}int t, k;int res[kMaxn];int a[kMaxn], b[kMaxn];int v1, v2;int main() {    scanf("%d%d", &t, &k);    for(int i = 1; i <= t; i++) {        int v;        scanf("%d", &v);        a[v]++;        v1 = max(v1, v);    }    v1++;    v2 = 1;    res[0] = 1;    while(k) {        if(k & 1)            Solve(res, a, v2, v1);        k>>=1;        Solve(a, a, v1, v1);    }    for(int i = 0 ; i<= v2; i++)        if(res[i])            printf("%d\n", i);    return 0;}
阅读全文
0 0
原创粉丝点击