标签:typename 题目 cond queue std 其他 乘法 div 思路
给定 \(n\) 和一个长度为 \(2^n\) 的数组 \(A\) (从 \(0\) 标号).
有一个初始为 \(0\) 的变量 \(x\) . 不断操作, 每次操作以 \(\frac {A_i}{\sum_{j=0}^{2^n-1} A_j}\) 的概率将 \(x\) 变成 \(x\ xor\ i\) .
对于所有 \(i\in[0,2^n)\) , 求出 \(x\) 第一次变成 \(i\) 的期望操作次数.
\(n\leqslant 18, 1\leqslant A\leqslant 1000\)
这题好神仙啊!对 FWT 的理解又多了一层。
可以看出来这种题的方程,有
于是有下面关系
容易发现只有 \(E_0\) 转移以后对不上,我们看看 t 具体是什么,有
怎么讲,容易发现每一个 \(E\) 都转移出去了,概率之和还是 \(E\),但每个 E 有自己加了 1,所以总共的期望值增加了 \(2^n\),又因为总期望值应该是不变的,所以得到 t 是 \(2^n\)
有 xor 乘法,我们把 E 和 P 都 FWT 一下,有
容易发现 \(FWT(I) = \left\{\begin{matrix} 2^n & (i=0)\\ 0 &(i \neq 0)\end{matrix}\right.\) 这样因为 \(FWT(P)_0 = 1\) 所以我们无法解出 \(FWT(E)_0\)
但其他的 \(FWT(E)_i\) 都可以解得,但是我们还知道 \(E_0=0\),所以先将 \(FWT(E)_0\) 设为 0 跑一遍 \(IFWT\),然后发现可以通过整体加减数来让 \(FWT_0\) 变化而其他的 \(FWT_i\) 不变,所以我们让所有的 \(E_i=E_i-E_0\) 即可,这样就能满足要求了。
/*
/> フ
| _ _|
/`ミ _x 彡
/ |
/ ヽ ?
/ ̄| | | |
| ( ̄ヽ__ヽ_)_)
\二つ
*/
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;
template <typename T>
void read(T &x) {
x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c==‘-‘) f=1;
for (;isdigit(c);c=getchar()) x=x*10+(c^48);
if (f) x=-x;
}
template<typename F>
inline void write(F x, char ed = ‘\n‘) {
static short st[30];short tp=0;
if(x<0) putchar(‘-‘),x=-x;
do st[++tp]=x%10,x/=10; while(x);
while(tp) putchar(‘0‘|st[tp--]);
putchar(ed);
}
template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }
template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }
const int N = 1000500;
const int P = 998244353;
ll fpw(ll x, ll mi) {
ll res = 1;
for (; mi; mi >>= 1, x = x * x % P)
if (mi & 1) res = res * x % P;
return res;
}
inline int add(int x, int y) {
return x + y >= P ? x + y - P : x + y;
}
int A[N], lim, n, inv2 = (P + 1) / 2;
void FWT_xor(int *A, int ty) {
for (int i = 1;i < lim; i <<= 1) {
for (int j = 0;j < lim; j += (i << 1)) {
int *f = A + j, *g = f + i;
for (int k = 0;k < i; k++) {
int x = f[k], y = g[k];
f[k] = add(x, y), g[k] = add(x, P - y);
if (ty == -1) f[k] = 1ll * f[k] * inv2 % P,
g[k] = 1ll * inv2 * g[k] % P;
}
}
}
}
int p[N], S;
int main() {
read(n), lim = 1 << n;
for (int i = 0;i < lim; i++) read(p[i]), S += p[i];
S = fpw(S, P - 2);
for (int i = 0;i < lim; i++) p[i] = 1ll * p[i] * S % P;
/* write(p[i], ‘ ‘); */
/* puts(""); */
FWT_xor(p, 1);
for (int i = 0;i < lim; i++) {
/* write(g[i], ‘ ‘), write(p[i]); */
ll up = i == 0 ? 0 : lim, dw = (p[i] + P - 1) % P;
/* write(up, ‘ ‘), write(dw); */
A[i] = up * fpw(dw, P - 2) % P;
}
FWT_xor(A, -1);
write(A[0], ‘ ‘), write(p[0]);
for (int i = 0;i < lim; i++) write(add(A[i], -A[0] + P));
return 0;
}
AT4996 [AGC034F] RNG and XOR(FWT)
标签:typename 题目 cond queue std 其他 乘法 div 思路
原文地址:https://www.cnblogs.com/Hs-black/p/13691168.html