简略题意:
n
种物品,每种物品有对应的权值,每种物品的数量没有限制。现在问取
假若只能取两个物品,就是一个很经典的生成函数问题,相当于做一次多项式乘法,可以用FFT去优化这个过程。现在我们做
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;
}