@atcoder - [email protected] RNG and XOR

目录

  • @[email protected]
  • @[email protected]
  • @accepted [email protected]
  • @[email protected]

@[email protected]

给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[0...2^N-1]。
该生成器有 \(\frac{A_i}{\sum A}\) 的概率生成 i,每次生成都是独立的。

现在有一个 X,初始为 0。每次操作生成一个随机数 v 并将 X 异或 v。

对于每一个 i ∈ [0, 2^N),求期望多少次操作 X 第一次等于 i。

原题题面

@[email protected]

不难想到期望 dp。定义 dp[i] 表示到达 i 的期望次数,则:

\[
dp[0] = 0 \dp[i] = (\sum_{j=0}^{2^N - 1}dp[j]\times p[i\oplus j]) + 1
\]

其中 \(p[i] = \frac{A_i}{\sum A}\)。

朴素做法是高斯消元。显然过不了。
对于高斯消元的常规优化是利用转移的图结构(比如 DAG,链或者树),但是这个题转移的图是完全图,做不到。

怎么办?观察转移式的结构,发现它其实是异或卷积。于是我们尝试走生成函数那一套。

如果用生成函数的记法,又可以将其记作 \(dp\oplus P + I = dp + k\times T\),其中 \(I[i] = 1, T[i] = [i = 0]\),\(k\) 是一个未知数。
注意当 n = 0 卷积是不成立的,所以需要在末尾填上一项 \(k\times T\)。

变一下形得到 \(dp\oplus (T - P) = I - k\times T\),两边同时进行 fwt 得到 \(dp'\times (T - P)' = I' - k\times T'\)。

注意到 \((T - P)'\) 的第 0 项始终为 0(根据 fwt 的定义可知),故 \(I' - k\times T'\) 的第 0 项也为 0,由此可以解出 k。

但是这样一来我们又不知道 \(dp'[0]\) 的值为多少,再次设未知数为 q。进行逆变换时把未知数代进去一起运算就可以了。

然后 \(dp\) 数列就可以表示成含 q 的一次函数,而根据 \(dp[0] = 0\) 可以反解出 q,于是 \(dp\) 数列就解出来了。

@accepted [email protected]

#include <cstdio>

const int MOD = 998244353;
const int INV2 = (MOD + 1) >> 1;

int add(int x, int y) {return (x + y >= MOD ? x + y - MOD : x + y);}
int sub(int x, int y) {return (x - y < 0 ? x - y + MOD : x - y);}
int mul(int x, int y) {return 1LL*x*y%MOD;}

int pow_mod(int b, int p) {
    int ret = 1;
    for(int i=p;i;i>>=1,b=mul(b,b))
        if( i & 1 ) ret = mul(ret,b);
    return ret;
}

struct node{
    int k, b;
    node() : k(0), b(0) {}
    node(int _k, int _b) : k(_k), b(_b) {}
    int get(int x) {return add(mul(k, x), b);}
    friend node operator + (node a, node b) {
        return node(add(a.k, b.k), add(a.b, b.b));
    }
    friend node operator - (node a, node b) {
        return node(sub(a.k, b.k), sub(a.b, b.b));
    }
    friend node operator * (node a, int k) {
        return node(mul(a.k, k), mul(a.b, k));
    }
    friend node operator / (node a, int k) {
        return a * pow_mod(k, MOD - 2);
    }
};

void fwt(node *A, int m, int type) {
    int n = (1 << m), f = (type == 1 ? 1 : INV2);
    for(int i=1;i<=m;i++) {
        int s = (1 << i), t = (s >> 1);
        for(int j=0;j<n;j+=s)
            for(int k=0;k<t;k++) {
                node x = A[j+k], y = A[j+k+t];
                A[j+k] = (x + y)*f, A[j+k+t] = (x - y)*f;
            }
    }
}

node A[1<<18], B[1<<18], C[1<<18], f[1<<18];

int main() {
    int N, M, S = 0; scanf("%d", &N), M = (1 << N);
    for(int i=0;i<M;i++) scanf("%d", &A[i].b), S = add(S, A[i].b);
    S = pow_mod(S, MOD - 2);
    for(int i=0;i<M;i++) A[i].b = sub(i == 0 ? 1 : 0, mul(A[i].b, S));
    for(int i=0;i<M;i++) B[i].b = 1;
    C[0].b = MOD - 1;
    fwt(A, N, 1), fwt(B, N, 1), fwt(C, N, 1);
    int tmp = mul(B[0].b, pow_mod(C[0].b, MOD-2));
    for(int i=1;i<M;i++)
        f[i] = (B[i] - C[i]*tmp) / A[i].b;
    f[0].k = 1; fwt(f, N, -1);
    int x = sub(0, mul(pow_mod(f[0].k, MOD-2), f[0].b));
    for(int i=0;i<M;i++) printf("%d\n", f[i].get(x));
}

@[email protected]

感觉我的做法很像是乱搞。。。不过我也不大清楚官方正解是啥子。。。

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12142184.html

时间: 2024-10-01 10:30:06

@atcoder - [email protected] RNG and XOR的相关文章

@atcoder - [email&#160;protected] Contest with Drinks Hard

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定序列 T1, T2, ... TN,你可以从中选择一些 Ti,可以选择 0 个(即不选). 定义你选择的权值 = (满足 T[L...R] 都被选择的区间 [L, R] 的数量)-(你选择的 Ti 之和),你希望这个权值尽量大. 现在有 M 次询问,每次询问假如将 T[Pi] 修改

@atcoder - [email&#160;protected] Colorful Tree

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 题面明天起来补... @[email protected] 跟颜色有关,虽然题目中说是要"修改"实际上每一个询问之间是独立的,即修改不会有时效性. 所以不难想到可以使用树上莫队. 首先将边的颜色与边权下放至点.然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S.区间

@atcoder - [email&#160;protected] Gachapon

目录 @[email protected] @solution - [email protected] @accepted code - [email protected] @solution - [email protected] @accepted code - [email protected] @[email protected] @[email protected] 一个随机数发生器会生成 N 种数. 第 i 种数有参数 Ai,记 SA = ∑Ai,随机数发生器会有 Ai/SA 的概率

@atcoder - [email&#160;protected] Simple Subsequence Problem

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定由若干长度 <= N 的 01 字符串组成的集合 S.请找到长度最长的串 t(如果有多个选字典序最小的),使得存在 >= K 个 S 中的字符串,使得 t 是这些字符串的子序列. 原题题面. @[email protected] 先看看怎么检验串 t 是否为某个串 s 的子序列:

@atcoder - [email&#160;protected] Two Trees

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定两棵树 A, B.现你需要构造一组值 (X1, X2, ..., XN)(两棵树编号相同的点对应权值相同),使得两棵树内任意子树的权值和的绝对值为 1. 无解输出 IMPOSSIBLE. 原题链接. @[email protected] 由于权值和为 1,可以推算出每个结点的奇偶性

@atcoder - [email&#160;protected] Next or Nextnext

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个长度为 N 的序列 a,问有多少排列 p,满足对于每一个 i,都有 \(a_i = p_i\) 或 \(a_i = p_{p_i}\) 成立. 原题传送门. @[email protected] 为了更直观地理解问题,不妨建个图:连有向边 \(i -> p_i\). 对于任意序

@atcoder - CODE FESTIVAL 2017 Final - [email&#160;protected] Tree MST

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定 N 个点,第 i 点有一个点权 Xi,再给定一棵边带权的树,第 i 条 (Ai, Bi) 边权为 Ci. 构建一个完全图,完全图中边 (i, j) 的边权为 dist(i, j) + Xi + Xj,其中 dist(i, j) 是点 i 与点 j 在树上的距离. 求该完全图的最小

GDCPC2016题解 by [email&#160;protected] | Asiimov

Problem A. ABCD 题目大意 给出一个四边形四条边AB.CD.AD.BC及两条对角线AC.BD的长度,问这个四边形的顶点能否在一个圆上 算法思路 通过余弦定理考察∠ACB与∠ADB是否相等即可. 时间复杂度: O(1) 代码 /** * Copyright ? 2016 Authors. All rights reserved. * * FileName: A.cpp * Author: Beiyu Li <[email protected]> * Date: 2016-05-09

@uoj - [email&#160;protected] 【UNR #2】黎明前的巧克力

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] Evan 和 Lyra 都是聪明可爱的孩子,两年前,Evan 开始为一个被称为UOJ的神秘的OI组织工作,在 Evan 与其他小伙伴的努力下,UOJ不仅成了OI界原创比赛的典范,更是因UR这一反人类难度的存在而举世闻名.然而今年,随着 Evan 前往世界彼岸,UOJ一天天减少着他的活力