• 子集卷积学习笔记


    子集卷积学习笔记

    [h_S=sum_{Lcup R=S,Lcap S=emptyset} f_Lg_R ]

    [f(i,S)=sum_{Tin S,|T|=i} f(T) ]

    这个对于每个 (i) 做一次FMT即可

    然后有

    [h(i,S)=sum_{j=0}^i f(j,S)g(i-j,S) ]

    交集为空集,那么元素个数加起来应该等于并集的元素个数

    最后直接IFWT即可

    其实本质就是按元素个数归类了一下。

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    } 
    #define ll long long
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
    #define ROF(i,a,b) for(register int i=(a);i>=(b);--i)
    const int mod = 1e9+9;
    #define add(a,b) a=a+b>=mod?a+b-mod:a+b
    #define del(a,b) a=a<b?a-b+mod:a-b
    const int N = 1<<20;
    int m,n,f[21][N],g[21][N],h[21][N],bi[N];
    void FWT(int *f,int opt){
    	for(register int l=2;l<=n;l<<=1){
    		int mid=l/2;
    		for(int *g=f;g!=f+n;g+=l){
    			FOR(i,0,mid-1){
    				if(opt==1) add(g[i+mid],g[i]);
    				else del(g[i+mid],g[i]);
    			}
    		}
    	}
    } 
    int main(){
    	m=read();n=1<<m;
    	FOR(i,0,n-1) bi[i]=bi[i>>1]+(i&1),f[bi[i]][i]=read();
    	FOR(i,0,n-1) g[bi[i]][i]=read();
    	FOR(i,0,m){
    		FWT(f[i],1);FWT(g[i],1);
    	}
    	FOR(i,0,m){
    		FOR(j,0,n-1){
    			FOR(k,0,i){
    				add(h[i][j],1ll*f[k][j]*g[i-k][j]%mod); 
    			}
    		}
    	}
    	FOR(i,0,m){
    		FWT(h[i],-1);
    	}
    	FOR(i,0,n-1){
    		printf("%d ",h[bi[i]][i]); 
    	}
    	return 0;
    }
    
  • 相关阅读:
    [导入]习惯修改别人的程序吗?
    [导入]感悟一首:"原来你也在这里"
    [导入]人生的高度
    [导入]nslookup工具的使用方法(转)
    [导入]回忆ASP!
    [导入]论坛的修改完成
    [导入]还原精灵安装失败!
    [导入]IE6无提示关闭窗口,不是利用activeX
    加密算法
    澄清VB调用API时字符串参数的困惑
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/12978741.html
Copyright © 2020-2023  润新知