zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    YbtOJ#573后缀表达【二分图匹配】
    CF605EIntergalaxy Trips【期望dp】
    YbtOJ#482爬上山顶【凸壳,链表】
    AT4996[AGC034F]RNG and XOR【FWT,生成函数】
    YbtOJ#903染色方案【拉格朗日插值,NTT,分治】
    YbtOJ#832鸽子饲养【凸包,Floyd】
    YbtOJ#463序列划分【二分答案,线段树,dp】
    CF618FDouble Knapsack【结论】
    P3214[HNOI2011]卡农【dp】
    YbtOJ#526折纸游戏【二分,hash】
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13442135.html
Copyright © 2011-2022 走看看