cf E. Thief in a Shop

传送门
其实是个假的多项式快速幂
(n)种物品里,选择(k)个物品,然后看有几种权值和有哪些

就是母函数模板吧,然后k次多项式乘法,而且是对于一个多项式来说,那就进行多项式快速幂。同时用fft维护,(真多项式快速幂应该不是这么简单)
如果说用ntt的话,要用双膜去求,因为只取一个膜会被使得多项式的值变成0的。其实我感觉就不能取模,所以还是fft维护比较好

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 3e6 + 5; // 刚好比n大的2的k次方再乘2
struct Complex{
    double x, y;
    Complex(double x = 0, double y = 0):x(x),y(y){};
    inline Complex operator + (const Complex b) const {
        return Complex(x + b.x,y + b.y);
    }
    inline Complex operator - (const Complex b) const {
        return Complex(x - b.x,y - b.y);
    }
    inline Complex operator * (const Complex b) const {
        return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
    }
};
namespace FFT{
    const double Pi = acos(-1);
    const int N = 3e6 + 5; // 刚好比n大的2的k次方再乘2
    Complex F[N], G[N];
    int r[N], n, m;
    void FFT(Complex *a, int n, int inv){
        for(int i = 0; i < n; i++)
            if(r[i] > i) swap(a[r[i]], a[i]);

       for(int mid = 2; mid <= n; mid <<= 1){
            Complex x(cos(2 * Pi / mid), inv * sin(2 * Pi / mid));
            for(int i = 0; i < n; i += mid){
                Complex w(1,0);
                for(int j = i; j < i + (mid >> 1); j++, w = w * x){
                    Complex t1 = a[j],t2 = a[j + (mid >> 1)] * w;
                    a[j] = t1 + t2; a[j + (mid >> 1)] = t1 - t2;
                }
            }
        }
    }
    void mul(int *a, int *b, int *c, int nn, int mm, int &k) {
        n = nn, m = mm;
        for(mm += nn, nn = 1; nn <= mm; nn *= 2);
        for(int i = 0; i <= nn; i++) F[i].x = F[i].y = G[i].x = G[i].y = 0;
        for(int i = 0; i <= n; i++) F[i].x = a[i];
        for(int i = 0; i <= m; i++) G[i].x = b[i];
        int l = 0;
        for(m += n, n = 1; n <= m; n *= 2, l++);
        for(int i = 0; i < n; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
        FFT(F, n, 1); FFT(G, n, 1);
        for(int i = 0; i < n; i++) F[i] = F[i] * G[i];
        FFT(F, n, -1);  k = m;
        for(int i = 0; i <= m; i++) {
            int x = int(F[i].x / n + 0.5);
            c[i] = x ? 1 : 0;
        }
    }
}
int a[N], b[N], ans[N];
int quick(int *a, int n, int k) {
    ans[0] = 1; int nu1 = n, nu2 = n;
    for(int i = 0; i <= n; i++) b[i] = a[i];
    while(k){
        if(k & 1) FFT::mul(ans, a, ans, nu1, nu2, nu1);
        FFT::mul(a, a, a, nu2, nu2, nu2);
        k >>= 1;
    }
    for(int i = 0; i <= nu1; i++) a[i] = ans[i];
    return nu1;
}
int main(){
    int n, m = 0, k; 
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++) {
        int x; scanf("%d", &x);
        a[x] = 1;
        m = max(m, x);
    }
    int num = quick(a, m, k);
    for(int i = 0; i <= num; i++)
        if(a[i]) printf("%d ", i);
    return 0;
}
原文地址:https://www.cnblogs.com/Emcikem/p/14247174.html