• 6467. 【GDOI2020模拟02.09】西行寺无余涅槃


    题目

    思考历程

    显然这题是道FWT。
    按照我非常浅的理解,我只想到了使用FWT的最暴力的做法。
    就一直想不到复杂度跟(k)有关的。


    正解

    这题是比赛三题中思想最难,但实现最简单的题目。
    首先讲讲那粗暴至极的思路:
    对于每一行,粗暴地建立一个多项式(请允许我这么叫),然后做FWT异或卷积。

    正解是在这个基础上进行优化。
    首先,基本操作,将(p_{i,j})异或上(p_{i,0}),把它当作不选时就是选了(a_0)
    可以发现,在FWT过后,只有(2^{k-1})种取值。(此时行的大小为(2^m)
    接着对每一列(指的是(n)排多项式中的一列,就是(2^m)列中的一列)单独考虑,
    如果是暴力,就直接将FWT后这些位置上的数都乘起来。
    但现在,我们统计对于(2^{k-1})种取值,每一种取值出现的次数。最后乘起来的时候一起乘。
    假如(k=3),那么这些取值分别是:
    (a_0+a_1+a_2,a_0-a_1+a_2,a_0+a_1-a_2,a_0-a_1-a_2)
    记这四种取值的出现次数分别为(x_0,x_1,x_2,x_3)
    (-)看成(1),把(+)看成(0),可以通过(a_1)(a_2)的符号来计算出(x)的下标。
    现在我们要将这四个东西都求出来。
    第一个限制:(x_0+x_1+x_2+x_3=n),原因不解释。

    先对每个(a)单独考虑。以(a_1)举例子:
    建立一个多项式,对于(iin [1,n]),在(p_{i,1})的位置加一。
    对这个多项式做一遍FWT,做完之后就对于每一项,它的值就是它对应的列的(x_0-x_1+x_2-x_3)的值。
    要解释这个,先说说异或FWT的实质:(FWT(F)_i=sum_{j=0}^{L-1}(-1)^{|iigcap j|}F_j)
    (|U|)表示的是(U)(1)的个数。
    推一下式子:(FWT(F)_i=sum_{j=0}^{2^m-1}(-1)^{|iigcap j|}sum_{k=0}^{n-1}|p_{k,1}=j|)
    (FWT(F)_i=sum_{k=0}^{n-1}(-1)^{|iigcap p_{k,1}|})
    对照一下FWT的实质,可以发现,对于第(i)列而言,这就是所有行对它的贡献之和。((FWT(A+B)=FWT(A)+FWT(B))所以贡献是可以合在一起计算的)
    而这些贡献是有正有负的。这个东西就可以理解为:正贡献的个数减去负贡献的个数。
    再看看(x)(x_0)(x_2)(a_1)是正贡献,(x_1)(x_3)(a_1)是负贡献,跟上面所述符合。
    类似地,对(a_2)考虑,可以求出(x_0+x_1-x_2-x_3)

    但是现在还缺一条方程。
    (p_{k,1} igoplus p_{k,2})带进去,(FWT(F)_i=sum_{k=0}^{n-1}(-1)^{|iigcap (p_{k,1} igoplus p_{k,2})|})
    与运算满足分配律:(a igcap(b igoplus c)=(aigcap b)igoplus (a igcap c))
    于是我们就明白了:这个东西相当于(a_1)(a_2)贡献符号相同的个数减去贡献符号不同的个数。在这里就是(x_0-x_1-x_2+x_3)
    推广一下,将正贡献记作(0),负贡献记作(1),那几个东西异或起来,求出的东西是异或为(0)的个数减去异或为(1)的个数。

    这样我们就可以凑出(2^{k-1})条方程,可以求解了。
    但是不能直接暴力解。
    观察一下:
    (x_0+x_1+x_2+x_3)
    (x_0-x_1+x_2-x_3)
    (x_0+x_1-x_2-x_3)
    (x_0-x_1-x_2+x_3)
    如果对FWT有点了解,就会发现这不就是(FWT({x_0,x_1,x_2,x_3}))嘛!
    所以做一遍IFWT,就可以解方程了。
    后面的操作就不用说了吧。
    时间复杂度:(O({2^k }(n+m*2^m)))


    代码

    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 1000010
    #define MK 20
    #define mo 998244353
    #define ll long long
    inline ll qpow(ll x,ll y=mo-2){
    //	printf("%lld
    ",y);
    	ll res=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			res=res*x%mo;
    	return res;
    }
    int n,m,K;
    int a[MK];
    int p[N][MK];
    ll space[1<<MK],point=0;
    ll *F[1<<MK],G[1<<MK],A[1<<MK],ans[1<<MK];
    inline void FWT(ll A[],int n){
    	for (int i=1;i<n;i<<=1)
    		for (int j=0;j<n;j+=i<<1)
    			for (int k=j;k<j+i;++k){
    				ll x=A[k],y=A[k+i];
    				A[k]=(x+y)%mo;
    				A[k+i]=(x-y+mo)%mo;
    			}
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    //	freopen("out.txt","w",stdout);
    	freopen("yuyuko.in","r",stdin);
    	freopen("yuyuko.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&K);
    	for (int i=0;i<K;++i)
    		scanf("%d",&a[i]);
    	int offset=0;
    	for (int i=1;i<=n;++i){
    		for (int j=0;j<K;++j)
    			scanf("%d",&p[i][j]);
    		offset^=p[i][0];
    		for (int j=1;j<K;++j)
    			p[i][j]^=p[i][0];
    		p[i][0]=0;
    	}
    	F[0]=space+point;
    	point+=1<<m;
    	for (int T=0;T<1<<m;++T)
    		F[0][T]=n;
    	for (int S=1;S<(1<<K-1);++S){
    		F[S]=space+point;
    		point+=1<<m;
    		for (int i=1;i<=n;++i){
    			int x=0;
    			for (int j=1;j<K;++j)
    				if (S>>j-1&1)
    					x^=p[i][j];
    			F[S][x]++;
    		}
    		FWT(F[S],1<<m);
    	}
    	for (int S=0;S<(1<<K-1);++S){
    		A[S]=a[0];
    		for (int j=1;j<K;++j)
    			if (S>>j-1&1)
    				A[S]-=a[j];
    			else
    				A[S]+=a[j];
    		A[S]=(A[S]%mo+mo)%mo;
    	}
    	for (int T=0;T<1<<m;++T){
    		for (int S=0;S<(1<<K-1);++S)
    			G[S]=F[S][T];
    		FWT(G,1<<K-1);
    		ans[T]=1;
    		ll inv=qpow(1<<K-1);
    		for (int j=0;j<(1<<K-1);++j)
    			(ans[T]*=qpow(A[j],G[j]*inv%mo))%=mo;
    	}
    	FWT(ans,1<<m);
    	ll inv=qpow(1<<m);
    	for (int T=0;T<1<<m;++T)
    		printf("%lld ",ans[T^offset]*inv%mo);
    	return 0;
    }
    

    总结

    FFT只会打板就算了,FWT千万不能只会打板啊!

  • 相关阅读:
    ArcObject获取ArcMap默认地理数据库的路径
    标准IO
    进程关系
    进程环境
    C语言基础知识位运算
    Bash 快捷键
    信号
    UNIX系统文件
    进程
    unix 文件属性
  • 原文地址:https://www.cnblogs.com/jz-597/p/12300760.html
Copyright © 2020-2023  润新知