• 【知识点】子集卷积


    简介:

    就是FWT加了一维个数。

    例题:

    给定长度为$2^n$的多项式a,b,求一个多项式c,使得$c_k = sum limits_{i& j=0,i|j=k}{a_i b_j}$。

    $nleq 20$。

    题解:

    普通的FWT能够解决$c_k = sum limits_{i|j=k}{a_i b_j}$的形式,考虑多的这个$i& j=0$的限制怎么办。

    我们给多项式$f_j$增加一维变成$f_{i,j}$,如果状态j中1的个数为i($siz_j =i$)则$f_{i,j}=a_{j}$,否则$f_{i,j}=0$。

    然后对于每个$f_i$所代表的多项式做一个子集和(正变换)。

    此时$f_{i,S}$代表S的子集中满足$siz_k =i$的子集k的系数之和。(类似地,令$g_{i,S}$代表b)

    现在就可以进行卷积了,令$h_i = sum limits_{j=0}^{i}{f_j * g_{i-j} }$。

    此时$h_{i,S}=sum limits_{k|jsubseteq S,siz_k + siz_j = i}{a_k b_j}$。

    我们再对每个$h_{i}$做一个子集差(逆变换),此时$h_{i,S}=sum limits_{k|j = S,siz_k + siz_j = i}{a_k b_j}$。

    那么第S项(状态S)的答案就是$c_{S}=h_{|S|,S}$。

    复杂度$O(n^{2}2^{n})$。(为啥洛谷的模板题卡常卡空间啊,我吐了)

    代码:

    #include<bits/stdc++.h>
    #define maxn 1048580
    #define maxm 21
    #define inf 0x7fffffff
    #define mod 1000000009
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    ll siz[maxn];
    struct poly{
        vector<int> a; ll n;
        inline void clear(){n=0;}
        inline void fwt(ll op){
            for(rint l=2;l<=n;l<<=1)
                for(rint i=0;i<n;i+=l)
                    for(rint j=i;j<i+l/2;j++)
                        a[j+l/2]=(a[j+l/2]+op*a[j]+mod)%mod;
        }
        poly operator+(const poly b)const{
            poly res; res.n=max(n,b.n);
            for(rint i=0;i<res.n;i++){
                if(i>=min(n,b.n)) res.a.push_back((n<b.n)?b.a[i]:a[i]);    
                else res.a.push_back((a[i]+b.a[i])%mod);
            }
            return res;
        }
        poly operator*(const poly b)const{
            poly res; res.n=max(n,b.n);
            for(rint i=0;i<res.n;i++){
                if(i>=min(n,b.n)) res.a.push_back(0);    
                else res.a.push_back(((ll)a[i]*(ll)b.a[i])%mod);
            }
            return res;
        }
    };
    
    inline ll read(){
        ll x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline poly calc(poly A,ll m){
        poly T; T.n=A.n;
        for(rint i=0;i<A.n;i++) 
            T.a.push_back((siz[i]==m)?A.a[i]:0);
        T.fwt(1); return T;
    }
    
    inline void print(poly A){
        printf("%d:",A.n);
        for(int i=0;i<A.n;i++) printf(" %d",A.a[i]);
        printf("
    ");
    }
    
    int main(){
        ll n=read(),m=1<<n; poly A,B; 
        A.clear(),B.clear(),A.n=B.n=m;
        for(rint i=0;i<m;i++) A.a.push_back(read());
        for(rint i=0;i<m;i++) B.a.push_back(read());
        for(rint i=0;i<m;i++)
            for(rint j=0;j<n;j++)
                siz[i]+=((i>>j)&1);
        poly RA[maxm],RB[maxm],R[maxm];
        for(ll i=0;i<=n;i++)
            RA[i]=calc(A,i),RB[i]=calc(B,i);
        for(rint i=0;i<=n;i++){
            R[i].n=0;
            for(rint j=0;j<=i;j++)
                R[i]=(R[i]+(RA[j]*RB[i-j]));
            R[i].fwt(-1);
        }
        for(rint i=0;i<m;i++)
            printf("%lld ",R[siz[i]].a[i]);
        printf("
    ");
        return 0;
    }
    子集卷积
  • 相关阅读:
    -_-#【H5】meta / href
    -_-#【CSS3】CSS3 gradient transition with background-position
    ♫【jQuery】detach
    -_-#setTimeout与setInterval
    -_-#【Mac】MacVim
    -_-#【jQuery】data
    ♫【Backbone】this
    -_-#【Better JS Code】严格模式
    ♫【Node】module.filename / __filename / __dirname / process.cwd() / require.main.filename
    【图片处理】ImageMagick, gm
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13265021.html
Copyright © 2020-2023  润新知