ECF R9(632E) & FFT

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;
}

 

posted @ 2016-04-19 11:55  YCuangWhen  阅读(279)  评论(0编辑  收藏  举报