• 【洛谷P4717】【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)


    题目

    题目链接:https://www.luogu.com.cn/problem/P4717
    给定长度为 (2^n) 两个序列 (A,B),设

    [C_i=sum_{joplus k = i}A_j imes B_k ]

    分别当 (oplus) 是 or,and,xor 时求出 (C)

    思路

    弃疗了,背板。
    Blog

    OR 的位矩阵及其逆矩阵

    [egin{bmatrix} 1&0 \1 &1 end{bmatrix} egin{bmatrix}1 &0 \-1 & 1end{bmatrix} ]

    AND 的位矩阵及其逆矩阵

    [egin{bmatrix} 1&1 \0 &1 end{bmatrix} egin{bmatrix}1 &-1 \0 & 1end{bmatrix} ]

    XOR 的位矩阵及其逆矩阵

    [egin{bmatrix} 1&1 \1 &-1 end{bmatrix} egin{bmatrix}frac{1}{2} &frac{1}{2} \frac{1}{2} & -frac{1}{2}end{bmatrix} ]

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=(1<<17)+10,MOD=998244353,inv2=499122177;
    const int C[7][2][2]=
    {
    	{{0,0},{0,0}},
    	{{1,0},{1,1}},{{1,0},{MOD-1,1}},
    	{{1,1},{0,1}},{{1,MOD-1},{0,1}},
    	{{1,1},{1,MOD-1}},{{inv2,inv2},{inv2,MOD-inv2}}
    };
    int n;
    ll f[N],g[N],X[N],Y[N];
    
    void FWT(ll *f,int type)
    {
    	for (int k=1;k<n;k<<=1)
    		for (int i=0;i<n;i+=(k<<1))
    			for (int j=0;j<k;j++)
    			{
    				ll x=f[i+j],y=f[i+j+k];
    				f[i+j]=(C[type][0][0]*x+C[type][0][1]*y)%MOD;
    				f[i+j+k]=(C[type][1][0]*x+C[type][1][1]*y)%MOD;
    			}
    }
    
    void Fmul(ll *f,ll *g,int type)
    {
    	memcpy(X,f,sizeof(X));
    	memcpy(Y,g,sizeof(Y));
    	FWT(X,type); FWT(Y,type);
    	for (int i=0;i<n;i++) X[i]=X[i]*Y[i]%MOD;
    	FWT(X,type+1);
    	for (int i=0;i<n;i++) printf("%lld ",X[i]);
    	printf("
    ");
    }
    
    int main()
    {
    	scanf("%d",&n);
    	n=(1<<n);
    	for (int i=0;i<n;i++) scanf("%lld",&f[i]);
    	for (int i=0;i<n;i++) scanf("%lld",&g[i]);
    	Fmul(f,g,1); Fmul(f,g,3); Fmul(f,g,5);
    	return 0;
    }
    
  • 相关阅读:
    c++-面向对象:类和对象
    c++-内联函数和函数重载和默认参数和函数指针
    c++-引用
    c++-const
    c++--语言本身
    排序-基数排序
    排序-归并排序
    排序-堆排序
    常用Java API: ArrayList(Vector) 和 LinkedList
    常用Java API:Calendar日期类
  • 原文地址:https://www.cnblogs.com/stoorz/p/14303202.html
Copyright © 2020-2023  润新知