• 【luogu AGC034F】RNG and XOR(FWT)


    RNG and XOR

    题目链接:luogu AGC034F

    题目大意

    给你一个长度为 2^n 的数组 A。
    一开始有一个 0 0 0 数,然后每次你随机给它异或上 0~2^n-1 中的数,随机到 i i i 的概率跟 Ai+1 成正比。
    然后对于 0~2^n-1 每个数问你第一次变成这个数的期望异或次数。

    思路

    考虑使用生成函数, f i f_i fi 为答案。

    f 0 = 0 f_0=0 f0=0
    f i = 1 + ∑ j = 0 2 n − 1 f i ⊕ j p j f_i=1+\sum\limits_{j=0}^{2^n-1}f_{i\oplus j}p_j fi=1+j=02n1fijpj
    F + f 0 ′ = I + F ∗ P F+f'_0=I+F*P F+f0=I+FP

    I = ∑ i = 0 2 n − 1 x i I=\sum\limits_{i=0}^{2^n-1}x^i I=i=02n1xi

    f 0 ′ f'_0 f0
    F = ∑ i = 0 ∞ f i x i F=\sum\limits_{i=0}^{\infty}f_ix^i F=i=0fixi
    S ( F ) = ∑ i = 0 ∞ f i S(F)=\sum\limits_{i=0}^{\infty} f_i S(F)=i=0fi
    S ( F ) + f 0 ′ = S ( I ) + S ( F ) ∗ S ( P ) S(F)+f'_0=S(I)+S(F)*S(P) S(F)+f0=S(I)+S(F)S(P)
    S ( P ) = 1 , S ( I ) = 2 n S(P)=1,S(I)=2^n S(P)=1,S(I)=2n
    f 0 ′ = 2 n f_0'=2^n f0=2n

    F + 2 n = I + F ∗ P F+2^n=I+F*P F+2n=I+FP
    F ( P − 1 ) = 2 n − I , F = 2 n − I P − 1 F(P-1)=2^n-I,F=\dfrac{2^n-I}{P-1} F(P1)=2nI,F=P12nI

    但是有一个问题就是 [ x 0 ] ( P − 1 ) [x^0](P-1) [x0](P1) 它 FWT 之后会是 0 0 0
    那就别管第 0 0 0 位,当他是 0 0 0 然后 IFWT。
    那我们还有一个限制条件是 f 0 = 0 f_0=0 f0=0,那你 IFWT 之后 0 0 0 会赋值到的位置是所有,但你现在没有了,那你 f 0 f_0 f0 现在的值是 − x -x x,那你给所有位置的值都加上 x x x,就相当于处理了 0 0 0 位置的贡献了。

    代码

    #include
    #define ll long long
    #define mo 998244353
    
    using namespace std;
    
    const int N = 1 << 18;
    int n;
    ll p[N], a[N], sum, I[N], f[N], inv2;
    
    ll ksm(ll x, ll y) {
    	ll re = 1;
    	while (y) {
    		if (y & 1) re = re * x % mo;
    		x = x * x % mo; y >>= 1;
    	}
    	return re;
    }
    
    void FWT(ll *f, int n, int op) {
    	for (int mid = 1; mid < n; mid <<= 1)
    		for (int R = (mid << 1), j = 0; j < n; j += R)
    			for (int k = 0; k < mid; k++) {
    				ll x = f[j | k], y = f[j | mid | k];
    				if (op == 1) {
    					f[j | k] = (x + y) % mo;
    					f[j | mid | k] = (x - y + mo) % mo;
    				}
    				else {
    					f[j | k] = (x + y) * inv2 % mo;
    					f[j | mid | k] = (x - y + mo) * inv2 % mo;
    				}
    			}
    }
    
    int main() {
    	inv2 = (mo + 1) / 2;
    	
    	scanf("%d", &n);
    	for (int i = 0; i < (1 << n); i++) scanf("%lld", &a[i]), (sum += a[i]) %= mo;
    	sum = ksm(sum, mo - 2); for (int i = 0; i < (1 << n); i++) p[i] = a[i] * sum % mo;
    	
    	p[0] = (p[0] - 1 + mo) % mo;
    	I[0] = (1 << n); for (int i = 0; i < (1 << n); i++) I[i] = (I[i] - 1 + mo) % mo;
    	
    	FWT(p, 1 << n, 1); FWT(I, 1 << n, 1);
    	for (int i = 1; i < (1 << n); i++) f[i] = I[i] * ksm(p[i], mo - 2) % mo;
    	FWT(f, 1 << n, -1);
    	
    	ll fix = f[0];
    	for (int i = 0; i < (1 << n); i++) f[i] = (f[i] - fix + mo) % mo;
    	for (int i = 0; i < (1 << n); i++) printf("%lld\n", f[i]);
    	
    	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
  • 相关阅读:
    排序——交换排序
    通用接口适配器使用文档须知
    基于SpringBoot的学生选课系统
    idea 导入项目
    VR科普研学基地科普开放日普乐蛙VR体验馆沉浸式体验设备
    【大数据技术】hive 跑mapreduce报错
    芯片制造过程2
    列表与字典—>一维列表
    手机号的正则表达式
    LeetCode 2344. 使数组可以被整除的最少删除次数 最大公约数
  • 原文地址:https://blog.csdn.net/weixin_43346722/article/details/127439600