zoukankan      html  css  js  c++  java
  • luogu P6097 子集卷积 FST FWT

    LINK:子集卷积

    学了1h多 终于看懂是怎么回事了(题解写的不太清楚 翻了好几篇博客才懂

    一个需要用到的性质 二进制位为1个数是i的二进制数s 任意两个没有子集关系。挺显然。

    而FST就是利用这个性质靠FWT做的。

    直接说做法:

    定义(f_{i,s})表示|s|为i状态为s的值.

    对于另一个g数组也同时定义。设答案为h.

    那么有 (h_{i,s}=sum_{j subseteq s}f_{|j|,j}cdot sum_{wsubseteq s,w|j==s}g_{i-|j|,w})

    暴力做这个还是(3^n) 但是可以发现此时限制松动了对于第二个状态我们不再要求交集为空了 但是如果交集不为空在第一个限制下.

    就会出现依然合法的情况. 所以只需要对(f_j,g_{i-j})进行或卷积即可.

    const int MAXN=300010,GG=3;
    int n,maxx;
    int sum[1<<20];
    int a[22][1<<20],b[22][1<<20],f[22][1<<20];
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int mux(int x,int y){return x-y<0?x-y+mod:x-y;}
    inline void FWT(int *a)
    {
    	for(int len=2;len<=maxx+1;len=len<<1)
    	{
    		int mid=len>>1;
    		for(int j=0;j<=maxx;j+=len)
    		{
    			for(int i=0;i<mid;++i)
    			{
    				a[i+j+mid]=add(a[i+j+mid],a[i+j]);
    			}
    		}
    	}
    }
    inline void IFWT(int *a)
    {
    	for(int len=2;len<=maxx+1;len=len<<1)
    	{
    		int mid=len>>1;
    		for(int j=0;j<=maxx;j+=len)
    		{
    			for(int i=0;i<mid;++i)
    			{
    				a[i+j+mid]=mux(a[i+j+mid],a[i+j]);
    			}
    		}
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);maxx=1<<n;--maxx;
    	rep(0,maxx,i)sum[i]=sum[i>>1]+(i&1),get(a[sum[i]][i]);
    	rep(0,maxx,i)get(b[sum[i]][i]);
    	rep(0,n,i)FWT(a[i]),FWT(b[i]);
    	rep(0,n,i)
    	{
    		rep(0,maxx,s)rep(0,i,j)f[i][s]=add(f[i][s],(ll)a[j][s]*b[i-j][s]%mod);
    		IFWT(f[i]);
    	}
    	rep(0,maxx,i)put_(f[sum[i]][i]);return 0;
    }
    
  • 相关阅读:
    物理层的三种编码方式
    Mysql中eft join、right join、inner join的区别
    Linux常用命令
    Linux中文件颜色所代表的属性和颜色
    phpcms v9 中的数据库操作函数
    NetBeans无法使用编码GBK安全打开文件
    PHP中的一些常用正则表达式
    eureka强制下线上线
    perl(JSON) is needed by mysql-community-test-5.7.30-1.el7.x86_64
    利用TikZ 宏包在 LaTeX 中绘制流程图
  • 原文地址:https://www.cnblogs.com/chdy/p/13027596.html
Copyright © 2011-2022 走看看