T2 AGC034F RNG and XOR

T2 AGC034F RNG and XOR

给定 n 和一个长度为 \(2^n\) 的数组 A (从 0 标号).

有一个初始为 0 的变量 x . 不断操作, 每次操作以 \(\frac {A_i}{\sum_{j=0}^{2^n-1} A_j}\) 的概率将 x 变成 x xor i .

对于所有 i∈[0,2n) , 求出 x 第一次变成 i 的期望操作次数.

n⩽18,1⩽A⩽1000

先转化一下,\(f[i]\) 表示i变成0的期望步数。(\(i >= 1\)

\(\large f[i] = 1 + \sum f[i \ xor \ j] \times p[j]\)

\(\large ?? + \sum_{i=1}^n (f[i] - 1) = \sum \sum f[i\ xor\ j] \times p[j]\)

由于 \(\sum p = 1\) 所以可以知道 $ ?? = f[0] + 2 ^ n - 1$

\((f[0] , f[1] , f[2] , ... , f[2^n-1]) * (p[0] , p[1] , p[2] , ... , p[2 ^n-1]) = (f[0] + 2^n - 1 , f[1] - 1 , f[2] - 1 , ... , f[2^n-1]-1)\)

给 p[0] 减个1

\((f[0] , f[1] , f[2] , ... , f[2^n-1]) * (p[0] - 1 , p[1] , p[2] , ... , p[2 ^n-1]) = (2^n - 1 , -1 , -1 , ... , -1)\)

做一遍FWT即可。 最后有个玄学的地方 f[0] 可能不等与 0 , 要让所有的f都减去一个 f[0]

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 1<<18|1 , mod = 998244353 , G = 3 , Ginv = (mod + 1) / 3 , inv2 = (mod + 1) / 2;
inline int read()
{
	register int x = 0 , f = 0; register char c = getchar();
	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
	return f ? -x : x;
}
int n , len;
int p[N] , q[N] , F[N];

inline int add(int a , int b) { a += b; return a >= mod ? a - mod : a; }
inline int mul(int a , int b) { return (LL)a * b % mod; }
inline int ksm(int a , int k) { int ans = 1; a %= mod; for( ; k ; k >>= 1 , a = mul(a , a)) if(k & 1) ans = mul(ans , a); return ans; }

void FWT(int *A , int opt)
{
	for(int mid = 1 ; mid < len ; mid <<= 1)
	{
		int siz = mid << 1;
		for(int j = 0 ; j < len ; j += siz)
		{
			for(int k = 0 ; k < mid ; ++k)
			{
				int a = A[j + k] , b = A[j + k + mid];
				if(opt == 1) 
					A[j + k] = add(a , b) , A[j + k + mid] = add(a , mod - b);
				else
					A[j + k] = mul(inv2 , add(a , b)) , A[j + k + mid] = mul(inv2 , add(a , mod - b));
			}
		}
	}
	return ;
}

int main()
{
	n = read(); len = 1 << n; int sum = 0;
	for(int i = 0 ; i < len ; ++i) sum += (p[i] = read());
	sum = ksm(sum , mod - 2);
	for(int i = 0 ; i < len ; ++i) p[i] = mul(p[i] , sum);
	for(int i = 1 ; i < len ; ++i) q[i] = mod - 1;
	q[0] = len - 1; p[0] = add(p[0] , mod - 1);
	FWT(q , 1); FWT(p , 1);
	for(int i = 1 ; i < len ; ++i) F[i] = mul(q[i] , ksm(p[i] , mod - 2));
	FWT(F , -1);
	int tmp = mod - F[0];
	for(int i = 0 ; i < len ; ++i) cout << add(tmp , F[i]) << '\n';
	return 0; 
}
posted @ 2020-05-31 06:26  沙野博士  阅读(87)  评论(0)    收藏  举报