• luogu P4717 【模板】快速沃尔什变换 (FWT)


    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define int long long
    
    using namespace std;
    
    const int N=1000000,M=998244353;
    int A[N],B[N],tmp_A[N],tmp_B[N],n,inv2;
    
    int ksm(int a,int b)
    {
    	int res=1;
    	while(b)
    	{
    		if(b&1)
    			res=res*a%M;
    		b>>=1,a=a*a%M;
    	}
    	return res;
    }
    
    void init()
    {
    	scanf("%lld",&n);
    	n=1<<n;
    	for (int i=0;i<n;i++)
    		scanf("%lld",&tmp_A[i]);
    	for (int i=0;i<n;i++)
    		scanf("%lld",&tmp_B[i]);
    	inv2=ksm(2,M-2);
    }
    
    void fwt_or(int A[],int flag)
    {
    	for (int l=1;l<n;l<<=1)
    		for (int i=0;i<n;i+=l<<1)
    			for (int j=0;j<l;j++)
    			{
    				int u=A[i+j],v=A[i+j+l];
    				if(flag==1)
    					A[i+j]=u,A[i+j+l]=(u+v)%M;
    				else
    					A[i+j]=u,A[i+j+l]=(v-u)%M;
    			}
    }
    
    void FWT_OR()
    {
    	for (int i=0;i<n;i++)
    		A[i]=tmp_A[i],B[i]=tmp_B[i];
    	fwt_or(A,1),fwt_or(B,1);
    	for (int i=0;i<n;i++)
    		A[i]=A[i]*B[i]%M;
    	fwt_or(A,-1);
    	for (int i=0;i<n;i++)
    		printf("%lld ",(A[i]+M)%M);puts("");
    }
    
    void fwt_and(int A[],int flag)
    {
    	for (int l=1;l<n;l<<=1)
    		for (int i=0;i<n;i+=l<<1)
    			for (int j=0;j<l;j++)
    			{
    				int u=A[i+j],v=A[i+j+l];
    				if(flag==1)
    					A[i+j]=(u+v)%M,A[i+j+l]=v;
    				else
    					A[i+j]=(u-v)%M,A[i+j+l]=v;
    			}
    }
    
    void FWT_AND()
    {
    	for (int i=0;i<n;i++)
    		A[i]=tmp_A[i],B[i]=tmp_B[i];
    	fwt_and(A,1),fwt_and(B,1);
    	for (int i=0;i<n;i++)
    		A[i]=A[i]*B[i]%M;
    	fwt_and(A,-1);
    	for (int i=0;i<n;i++)
    		printf("%lld ",(A[i]+M)%M);puts("");
    }
    
    void fwt_xor(int A[],int flag)
    {
    	for (int l=1;l<n;l<<=1)
    		for (int i=0;i<n;i+=l<<1)
    			for (int j=0;j<l;j++)
    			{
    				int u=A[i+j],v=A[i+j+l];
    				if(flag==1)
    					A[i+j]=(u+v)%M,A[i+j+l]=(u-v)%M;
    				else
    					A[i+j]=(u+v)%M*inv2%M,A[i+j+l]=(u-v)%M*inv2%M;
    			}
    }
    
    void FWT_XOR()
    {
    	for (int i=0;i<n;i++)
    		A[i]=tmp_A[i],B[i]=tmp_B[i];
    	fwt_xor(A,1),fwt_xor(B,1);
    	for (int i=0;i<n;i++)
    		A[i]=A[i]*B[i]%M;
    	fwt_xor(A,-1);
    	for (int i=0;i<n;i++)
    		printf("%lld ",(A[i]+M)%M);puts("");
    }
    
    void work()
    {
    	FWT_OR(),FWT_AND(),FWT_XOR();
    }
    
    signed main()
    {
    //	freopen("P4717.in","r",stdin);
    //	freopen("P4717.out","w",stdout);
    	init();
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    洛谷 4035 [JSOI2008]球形空间产生器
    洛谷 2216 [HAOI2007]理想的正方形
    洛谷2704 [NOI2001]炮兵阵地
    洛谷2783 有机化学之神偶尔会做作弊
    洛谷 2233 [HNOI2002]公交车路线
    洛谷2300 合并神犇
    洛谷 1641 [SCOI2010]生成字符串
    Vue history模式支持ie9
    VUE实现登录然后跳转到原来的页面
    vue history模式 apache配置
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13442135.html
Copyright © 2020-2023  润新知