Description:
上一篇blog.
Solution:
同样我们可以用fft来做...就像上次写的那道3-idoit一样,对a做k次卷积就好了.
同样有许多需要注意的地方:我们只是判断可行性,所以为了保证精度如果f大于1就把它变成1; 对于长度也可以慢慢倍增,可以优化复杂度就是写起来麻烦.
void change(complex y[],int len) { int i,j,k; for(i = 1, j = len/2;i < len-1; i++) { if(i < j)swap(y[i],y[j]); k = len/2; while( j >= k) { j -= k; k /= 2; } if(j < k) j += k; } } void fft(complex y[],int len,int on) { change(y,len); for(int h = 2; h <= len; h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); for(int j = 0;j < len;j+=h) { complex w(1,0); for(int k = j;k < j+h/2;k++) { complex u = y[k]; complex t = w*y[k+h/2]; y[k] = u+t; y[k+h/2] = u-t; w = w*wn; } } } if(on == -1) for(int i = 0;i < len;i++) y[i].r /= len; } const int maxn = 2e6+5; complex x1[maxn], x2[maxn]; int a[maxn], b[maxn]; void cal(int *a, int *b, int &lena, int &lenb) { int len = 1; while(len<lena+lenb) len<<=1; for(int i = 0; i<=lenb; i++) { x1[i] = complex(b[i], 0); } for(int i = lenb+1; i<len; i++) x1[i] = complex(0, 0); for(int i = 0; i<=lena; i++) { x2[i] = complex(a[i], 0); } for(int i = lena+1; i<len; i++) x2[i] = complex(0, 0); fft(x1, len, 1); fft(x2, len, 1); for(int i = 0; i<len; i++) x1[i] = x1[i]*x2[i]; fft(x1, len, -1); for(int i = 0; i<=lena+lenb; i++) b[i] = (int)(x1[i].r+0.5); for(int i = 0; i<=lena+lenb; i++) if(b[i]>0) b[i] = 1; lenb += lena; } int main() { int n, k, x; cin>>n>>k; for(int i = 0; i<n; i++) { scanf("%d", &x); a[x]++; } b[0] = 1; int lena = 1000, lenb = 0; while(k) { if(k&1) { cal(a, b, lena, lenb); } if(k>1) { cal(a, a, lena, lena); } k>>=1; } for(int i = 0; i<=lena+lenb; i++) { if(b[i]) { printf("%d ", i); } } cout<<endl; return 0; }