• 子集卷积


    /*
    如代码所示
    设p(x)表示x二进制拆分后1的个数 
    题目要求维护的i&j==0 且 i|j=k 实际上就是 就是i|j=k 且p(i)+p(j)=p(k)
    很容易理解
    然后我们考虑将FMT拆成两维来同时维护这两个要求
    把a[i]插入f[p(i)][i]中,b[i]插入g[p(i)][i]中
    然后对每个f[0~lim],g[0~lim]做fmt
    然后暴力区间合并维护p(i)+p(j)=p(k)这个条件即可 
    时间复杂度O(2^n*n^2)
    */ 
    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dwn(i,a,b) for(int i=a;i>b=;i--)
    #define MAXN 1500000
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        while('0'>ch || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while('0'<=ch && ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    typedef long long ll;
    const int mod=1e9+9;
    int check(int x){
        int res=0;
        while(x){
            if(x&1) res++;
            x>>=1;
        }
        return res;
    }
    int n,lim,f[22][MAXN],g[22][MAXN],h[22][MAXN];
    void FWT_or(int *a,int opt){
        for(int i=1;i<n;i<<=1)
            for(int j=0,p=(i<<1);j<n;j+=p)
                rep(k,0,i-1)
                    if(opt==1) a[j+i+k]=(a[j+i+k]+a[j+k])%mod;
                    else a[j+i+k]=(a[j+i+k]+mod-a[j+k])%mod;
    }
    main(){
    //    freopen("my.out","w",stdout);
        n=read();
        lim=n; n=(1<<n);
    //    rep(i,0,n-1) cout<<check(i)<<" ";cout<<endl;
        rep(i,0,n-1) f[check(i)][i]=read();
        rep(i,0,n-1) g[check(i)][i]=read();
        rep(i,0,lim) FWT_or(f[i],1),FWT_or(g[i],1);
        
        rep(i,0,lim){
            rep(j,0,i){
                rep(k,0,n-1) h[i][k]=(h[i][k]+(1ll*f[j][k]*g[i-j][k])%mod)%mod;
            }
        }
        rep(i,0,lim) FWT_or(h[i],-1);
        rep(i,0,n-1) printf("%d ",h[check(i)][i]);
        return 0;
    }
  • 相关阅读:
    js 多物体运动
    js运动 淡入淡出
    js运动 分享到
    正则 重复项最多得子项
    jq 拖拽
    jq 弹出窗口
    jq 选项卡
    jq 写法
    Codeforces 185A Plant( 递推关系 + 矩阵快速幂 )
    HDU 2604 Queuing( 递推关系 + 矩阵快速幂 )
  • 原文地址:https://www.cnblogs.com/handsome-zlk/p/14359169.html
Copyright © 2020-2023  润新知