• 【笔记】FWT 快速沃尔什变换


    参考资料

    学习笔记1
    学习笔记2

    题目汇总

    • bzoj4589 Hard Nim
      设每堆石子个数是a1,a2,a3...ak,先手必胜的条件是a1 xor a2 xor a3 ... ak == 0
      fwt可以计算下标求xor 等于一个定值的数的乘积的和, 因为要求所有石子堆数都是质数,所以给要卷积的数组,质数赋值为1,合数赋值为0,这样只有所有的数字都是1乘积才为1,求和后就是总的方案数
    • 51nod1773 A国的贸易
      每过一天,城市i的商品数就变成a[i] = a[i] + ∑a[j] (j xor i==2^m)
      令b数组为b[0]=1,b[2^m]=1,其余为0
      异或具有自反性质,所以 a[k] = ∑ a[i]*b[j] (i xor j = k) 当j为2^m时b才为1
      这满足fwt_xor 应用条件,t天就乘t个b,用快速幂加速即可
    • 牛客多校第九场A Circulant Matrix 纯裸沙比题,不放代码了
    • 2018沈阳onsite I Distance Between Sweethearts 博客有题解

    模板

    最常见的是 xor 题目,结合自反性质构造卷积式

    void fwt_xor(ll a[], int len, int on){
    	int inv2 = 500000004;
    	for (int i = 1; i < len; i <<= 1)
    		for (int p = i<<1, j = 0;j < len; j += p)
    			for (int k = 0; k < i; k++) {
    				int x = a[j + k], y = a[i + j + k];
    				a[j + k] = (x + y) % MOD;
    				a[j + k + i] = (x - y + MOD) % MOD;
    				if (on == -1) {
    					a[j + k] = a[j + k] * inv2 % MOD;
    					a[i + j + k] = a[i + j + k] * inv2 % MOD;
    				}
    			}
    }
    
    void fwt(ll a[],int n,int v) {
        for(int d=1;d<n;d<<=1) {
    	for(int m = d<<1,i=0;i<n;i+=m) {
    	    for(int j=0;j<d;j++){
    		ll x = a[i+j],y = a[i+j+d];
    		if(v == 1) a[i+j] = (x+y),a[i+j+d] = (x-y);
    		else a[i+j] = (x+y)/2,a[i+j+d] = (x-y)/2;
    	    }
    	}
        }
    }
    

    此外还有 or 以及 and 的代码 (未使用过)

    void fwt_and(ll a[], int len, int on)
    {
        for(int i = 1;i < len;i <<= 1)
            for(int p = i << 1, j = 0; j < len; j += p)
                for(int k = 0; k < i; k++)
                    if(on == 1)a[j + k]=(a[j + k] + a[i + j + k]) % MOD;
                    else a[j + k]=(a[j + k] + MOD - a[i + j + k]) % MOD;
    }
    
    void fwt_or(ll a[], int len, int on)
    {
        for(int i = 1;i < len;i <<= 1)
            for(int p = i << 1, j = 0; j < len; j += p)
                for(int k = 0; k < i; k++)
                    if(on == 1)a[i + j + k]=(a[j + k] + a[i + j + k]) % MOD;
                    else a[i + j + k]=(a[i + j + k] + MOD - a[j + k]) % MOD;
    }
    
  • 相关阅读:
    函数的存储 堆和栈
    函数的容错处理 函数的返回值
    Linux启动故障排查和修复技巧
    干货 | 亿级Web系统负载均衡几种实现方式
    利用expect批量修改Linux服务器密码
    干货 | LVM快照学习
    实战 | Linux根分区扩容
    LVM 逻辑卷学习
    Shell脚本实战:日志关键字监控+自动告警
    手把手教你在Linux中快速检测端口的 3 个小技巧
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9492404.html
Copyright © 2020-2023  润新知