zoukankan      html  css  js  c++  java
  • 【洛谷6097】【模板】子集卷积

    点此看题面

    大致题意: 给定(a_{0sim 2^n-1},b_{0sim 2^n-1}),求(c_{0sim 2^n-1})满足(c_k=sum_{i|j=k,i&j=0}a_ib_j)

    子集卷积

    做这个之前,要先了解(FWT)

    考虑只要用(FWT)做或卷积,就可以轻松满足(i|j=k)这一限制,可要同时满足(i&j=0),似乎没法直接搞。

    但是,稍加分析我们就会发现,这两个限制放在一起其实会产生一个奇妙的性质。

    因为(i&j=0),所以(i)(j)不可能在同一位上存在(1),而(i|j=k),则(k)的每一位上的(1)应该被恰好分给(i)(j)的其中一个。

    换言之,(i)(j)二进制下(1)的个数之和等于(k)二进制下(1)的个数。

    于是,我们定义(f_{i,j},g_{i,j})表示:((cnt(j))(j)二进制下(1)的个数)

    [f_{i,j}=egin{cases}a_j&i=cnt(j)\0&i ot=cnt(j)end{cases},g_{i,j}=egin{cases}b_j&i=cnt(j)\0&i ot=cnt(j)end{cases} ]

    然后我们令,(ans_i=sum_{j=0}^if_j*g_{i-j}),则(c_i=ans_{cnt(i),i})

    注意,这里的(*)(FWT)的或卷积,因此上式可以看作是卷积套卷积,只不过外层这个卷积(nle20),完全无需优化而已。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 20
    #define X 1000000009
    using namespace std;
    int n,P,a[N+5][1<<N],b[N+5][1<<N],ans[N+5][1<<N],g[1<<N];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc(' ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    I void FWT(int *s,CI op)//FWT或卷积
    {
    	RI i,j,k;for(i=1;i^P;i<<=1) for(j=0;j^P;j+=i<<1)
    		for(k=0;k^i;++k) s[i+j+k]=(1LL*op*s[j+k]+s[i+j+k])%X;
    }
    int main()
    {
    	RI i,j,k;for(F.read(n),P=1<<n,i=0;i^P;++i) g[i]=g[i>>1]+(i&1);//预处理每个数二进制下1的个数
    	for(i=0;i^P;++i) F.read(a[g[i]][i]);for(i=0;i^P;++i) F.read(b[g[i]][i]);//读入
    	for(i=0;i<=n;++i) FWT(a[i],1),FWT(b[i],1);for(i=0;i^P;++i)//先做DWT
    		for(j=0;j<=n;++j) for(k=0;k<=j;++k) ans[j][i]=(1LL*a[k][i]*b[j-k][i]+ans[j][i])%X;//求出ans数组
    	for(i=0;i<=n;++i) FWT(ans[i],X-1);for(i=0;i^P;++i) F.write(ans[g[i]][i]);return F.clear(),0;//做IDWT,输出答案
    }
    
  • 相关阅读:
    win7共享打印机如何设置,xp系统如何连接共享打印机。
    FTP服务-filezilla server 配置
    imp导入时 出现IMP-00017:由于 ORACLE 错误 6550, 以下语句失败: 解决方法
    抓取行政区域js代码
    docker 安装 yapi
    docker 搭建 zipkin
    docker 安装 mindoc
    centos 更换源以及安装软件
    springboot 服务卡死 连接池查询无响应问题解决
    -- Add the primary key as part of the CREATE TABLE statement in case `innodb_force_primary_key` is enabled by flyway
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/FST.html
Copyright © 2011-2022 走看看