• FWT小结


    核心思想:把 a , b a,b a,b 化成 f w t ( a ) , f w t ( b ) fwt(a),fwt(b) fwt(a),fwt(b),相乘后再化为 a a a

    化的过程用的是分治

    所以和FFT其实一模一样

    OR / AND 卷积

    不需要什么技巧,暴力分治转移即可

    每次分治下去,相当于位数减一

    注意合并过程中我们是计算对应位的贡献

    因为其它位的贡献我们在分治下去时已经计算了

    后面区间其他数贡献到前面某个位置已经统计到后面的那个位置了
    在这里插入图片描述

    OR

    在这里插入图片描述
    在这里插入图片描述
    考虑如何还原

    对上面式子进行换元即可

    在这里插入图片描述

    void OR(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1)
    		for(i=0; i<n; i+=o)
    			for(j=0; j<k; ++j) 
    				f[i+j+k]=(f[i+j+k]+f[i+j]*x)%mo; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    AND

    反过来好像就行了

    在这里插入图片描述

    void AND(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1)
    		for(i=0; i<n; i+=o)
    			for(j=0; j<k; ++j) 
    				f[i+j]=(f[i+j]+f[i+j+k]*x)%mo; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    XOR卷积

    这个需要点技巧

    首先考虑若有转移系数,必须满足以下条件:

    在这里插入图片描述

    我们可以用以下方法构造:

    在这里插入图片描述

    构造的原理:

    异或前后 1 的个数的奇偶性不变

    因此得证:

    在这里插入图片描述

    在这里插入图片描述

    所以有:

    在这里插入图片描述

    我们把它写成这个形式:

    在这里插入图片描述

    然后考虑如何FWT和IFWT

    思考分治过程中popcount的变化

    在这里插入图片描述

    因此合并的过程可以表示为:

    在这里插入图片描述

    换元一下可以得到其逆变换:

    在这里插入图片描述

    void XOR(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1) 
    		for(i=0; i<n; i+=o) 
    			for(j=0; j<k; ++j) {
    				f[i+j]+=f[i+j+k]; 
    				f[i+j+k]=f[i+j]-2*f[i+j+k]; 
    				f[i+j]=f[i+j]*x%mo; f[i+j+k]=f[i+j+k]*x%mo; 
    			}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    板子

    #include
    using namespace std;
    #define int long long
    inline int read(){int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
    ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
    (x<<3)+(ch^48);ch=getchar();}return x*f;}
    #define Z(x) (x)*(x)
    #define pb push_back
    //#define M
    #define mo 998244353
    #define N 200010
    int pw(int a, int b) {
    	int ans=1; 
    	while(b) {
    		if(b&1) ans*=a; 
    		a*=a; b>>=1; 
    		ans%=mo; a%=mo; 
    	}
    	return ans; 
    }
    const int inv2=pw(2, mo-2); 
    int n, m, i, j, k, T;
    int a[N], b[N], A[N], B[N], o; 
    
    void cp() {
    	for(i=0; i<n; ++i) a[i]=A[i], b[i]=B[i]; 
    }
    
    void pr() {
    	for(i=0; i<n; ++i) printf("%lld ", (a[i]%mo+mo)%mo); 
    	printf("\n"); 
    }
    
    void mul() {
    	for(i=0; i<n; ++i) a[i]=a[i]*b[i]%mo; 
    }
    
    void OR(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1)
    		for(i=0; i<n; i+=o)
    			for(j=0; j<k; ++j) 
    				f[i+j+k]=(f[i+j+k]+f[i+j]*x)%mo; 
    }
    
    void AND(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1)
    		for(i=0; i<n; i+=o)
    			for(j=0; j<k; ++j) 
    				f[i+j]=(f[i+j]+f[i+j+k]*x)%mo; 
    }
    
    void XOR(int *f, int x) {
    	for(k=1, o=2; o<=n; o<<=1, k<<=1) 
    		for(i=0; i<n; i+=o) 
    			for(j=0; j<k; ++j) {
    				f[i+j]+=f[i+j+k]; 
    				f[i+j+k]=f[i+j]-2*f[i+j+k]; 
    				f[i+j]=f[i+j]*x%mo; f[i+j+k]=f[i+j+k]*x%mo; 
    			}
    }
    
    signed main()
    {
    //	freopen("in.txt", "r", stdin);
    //	freopen("out.txt", "w", stdout);
    //	srand(time(NULL));
    //	T=read();
    //	while(T--) {
    //
    //	}
    	n=read(); n=(1<<n); 
    	for(i=0; i<n; ++i) A[i]=read(); 
    	for(i=0; i<n; ++i) B[i]=read(); 
    	cp(); OR(a, 1); OR(b, 1); mul(); OR(a, -1); pr(); 
    	cp(); AND(a, 1); AND(b, 1); mul(); AND(a, -1); pr(); 
    	cp(); XOR(a, 1); XOR(b, 1); mul(); XOR(a, inv2); pr(); 
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
  • 相关阅读:
    mysql高阶sql语句
    七天速通javaSE:第二天 基础:标识符与数据类型
    使用XXL-JOB自定义任务并调度
    品牌线上控价,如何平台投诉
    OSG嵌入QT的简明总结2
    sql concat()函数
    Python入门教学——if __name__==‘__main__‘:
    Trino 391 安装配置
    ky10 server x86 安装、更新openssl3.1.4(在线编译安装、离线安装)
    Allegro Design Entry HDL(OrCAD Capture HDL)连线管理菜单详细介绍
  • 原文地址:https://blog.csdn.net/zhangtingxiqwq/article/details/132922605