首页 > 其他分享 >[ARC185D] Random Walk on Tree 题解

[ARC185D] Random Walk on Tree 题解

时间:2024-10-18 20:33:19浏览次数:7  
标签:nonumber frac int 题解 Random long Walk inline mod

一个很套路的做法。

思路

题目要求走完整个树的时间,这并不好算,容易想到 min-max 容斥。

依据 min-max 容斥,我们可以轻松把它转化成第一次走到所有子集的时间。

考虑在这道题中,有什么特殊的。

第一,任何包含根节点的子集答案都是零。

第二,由于我们只关心第一次走到的点的时间,因此假如一个点的祖先被选中,那么这个点是否选中是无关紧要的。

这些无关紧要的点地位相同,所以我们可以一起考虑。

假设有 \(n\) 个点是无关紧要的。

它们对答案的贡献是什么呢?

是:

\[(-1)^k\sum_{i=0}^n (-1)^i\binom{n}{i} \]

这是非常令人熟悉的二项式定理。

因此:

\[(-1)^k\sum_{i=0}^n (-1)^i\binom{n}{i} =(-1)^k[n=0] \]

我们发现,只有当 \(n=0\) 的时候才对答案有贡献。

在 \(n=0\) 的时候,每一条链只有最底部的点可能被选。

现在计算这样的时间即可。

首先,对于底部被选的链而言。

我们设 \(f_i\) 表示到达深度为 \(i\) 的点还要走的期望步数,根节点的深度为 \(0\)。

那么有:

\[\begin{align} f_m&=0\nonumber\\ f_{m-1}&=\frac{(f_m+f_{m-2})}{2}+1\nonumber\\ &=\frac{f_{m-2}}{2}+1\nonumber\\ f_{m-2}&=\frac{f_{m-3}+f_{m-1}}{2}+1\nonumber\\ &=\frac{f_{m-3}+\frac{f_{m-2}}{2}+1}{2}+1\nonumber\\ &=\frac{2f_{m-3}}{3}+2\nonumber\\ f_{m-i}&=\frac{if_{m-i-1}}{i+1}+i\nonumber\\ \end{align} \]

对于底部没有被选的链而言。

有:

\[\begin{align} f_n&=f_{m-1}+1\nonumber\\ f_{m-1}&=\frac{(f_n+f_{m-2})}{2}+1\nonumber\\ &=f_{m-2}+3\nonumber\\ f_{m-i}&=f_{m-i}+2\times i +1\nonumber\\ \end{align} \]

所有期望都可以推到根上。

因此,假设有 \(i\) 条链被选,则有 \((n-i)\) 条链没有被选:

\[f_{0}=\frac{i(\frac{(m-1)f_0}{m}+m-1)+(n-i)(f_0+2\times m-1)}{n}+1 \]

可以继续化简。

\[\begin{align} f_{0}&=\frac{i(\frac{(m-1)f_0}{m}+m-1)+(n-i)(f_0+2\times m-1)}{n}+1\nonumber\\ \frac{i}{n}f_{0}&=\frac{i(\frac{(m-1)f_0}{m}+m-1)+(n-i)(2\times m-1)}{n}+1\nonumber\\ (\frac{i}{n}-\frac{i(m-1)}{nm})f_{0}&=\frac{i(m-1)+(n-i)(2\times m-1)}{n}+1\nonumber\\ (i-\frac{i(m-1)}{m})f_{0}&=i(m-1)+(n-i)(2\times m-1)+n\nonumber\\ \frac{i}{m}f_{0}&=i(m-1)+(n-i)(2\times m-1)+n\nonumber\\ \end{align} \]

算出 \(f_0\) 后,不要忘记乘负一和组合数的系数。

时间复杂度:\(O(n\log mod)\)。

瓶颈在求逆元,可以线性预处理,但没有必要。

Code

/*
  ! 前途似海,来日方长。
  ! Created: 2024/10/13 21:48:58
*/
#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second
#define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
inline void JYFILE19();

using i64 = long long;
using pii = pair<int, int>;

bool ST;
const int N = 1e6 + 10;
const int mod = 998244353;

int n, m;

namespace Math {
int Fc[1000010], Iv[1000010];
template<typename T> inline void add(T&x, int y) { if ((x += y) >= mod) x -= mod; }
template<typename T> inline void del(T&x, int y) { if ((x -= y) < 0) x += mod; }
template<typename T> inline void add(T&x, int y, int z) { x = (x + (long long) y * z) % mod; }
template<typename T> inline void mo(T&x) { x = (x % mod + mod) % mod; }
inline long long power(long long x, long long y) {
  long long res = 1;
  while (y) { if (y & 1) res = res * x % mod; x = x * x % mod, y /= 2; }
  return res;
}
inline void init(int n) {
  Fc[0] = 1;
  for (int i = 1; i <= n; i++) Fc[i] = (long long) Fc[i - 1] * i % mod; Iv[n] = power(Fc[n], mod - 2);
  for (int i = n; i >= 1; i--) Iv[i - 1] = (long long) Iv[i] * i % mod;
}
inline long long C(int x, int y) { return (x < 0 || y < 0 || x < y ? 0 : (long long) Fc[x] * Iv[y] % mod * Iv[x - y] % mod); }
} using namespace Math;

signed main() {
  JYFILE19();
  cin >> n >> m, init(n);
  int ns = 0;
  fro(i, 1, n) {
    int x = C(n, i);
    int up = (i * (m - 1) + (n - i) * (2 * m - 1)) % mod;
    int dw = (i * power(m, mod - 2)) % mod;
    int sm = ((up + n) * power(dw, mod - 2)) % mod;
    ns = (ns + (i & 1 ? 1 : -1) * x * sm) % mod;
  }
  cout << (ns % mod + mod) % mod << "\n";
  return 0;
}

bool ED;
inline void JYFILE19() {
  // freopen(".in", "r", stdin);
  // freopen(".out", "w", stdout);
  srand(random_device{}());
  ios::sync_with_stdio(0), cin.tie(0);
  double MIB = fabs((&ED - &ST) / 1048576.), LIM = 32;
  cerr << "MEMORY: " << MIB << endl, assert(MIB <= LIM);
}

标签:nonumber,frac,int,题解,Random,long,Walk,inline,mod
From: https://www.cnblogs.com/JiaY19/p/18475000

相关文章

  • ZZJC新生训练赛第五场题解
    A题思路题目要求构造一个相邻两项互质的长度为n的序列。可以直接选择输出从1到n的自然数序列,因为相邻的自然数总是互质的。题目有多个测试用例,因此需要逐个处理输入,并输出对应结果。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_wit......
  • 题解:[YNOI2019] 游戏
    ProblemLink[YNOI2019]游戏题外话第一眼,由乃?不打不打。第二眼,欸noi三个字母怎么是大写(才发现是云南省选)。题意题意简洁,不再赘述。Solution一眼看出概率dp,但如何似乎没思路?开始公式做题:设置状态+推转移式。\(Q1\):怎么设置状态?首先,思考一个问题:第\(k\)个人该怎么“......
  • 异常问题解决
    异常:java程序编译或运行过程中出现的问题Throwable:Error:表示非常严重的问题,自己无法解决的问题Exception:除了RuntimeException其它异常【编译时期异常】:一般指的是异常尚未处理就编译了RuntimeException【运行时期异......
  • PTA L1系列题解(C语言)(L1_081 -- L1_088)
    L1-081今天我要赢题目内容:2018年我们曾经出过一题,是输出“2018我们要赢”。今年是2022年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。输入格式:本题没有输入。输出格式:输出分2行。在第一行中输出I'mgonnawin!Today!,在第二行中用年年年......
  • P1955 程序自动分析 题解
    P1955程序自动分析一道并查集的裸题,并查集存储传递性,后判断。主题思路十分简单,重点在于离散化与离线的处理。离散化,为什么会想到离散化呢,观察数据范围\(1<i,j<{10}^9\),数据范围过大,导致数组不可能开到\(1e9\)但是\(1<n<1e5\)考虑到每次输入只有两个数,若每个数都两两不同,......
  • 【题解】[Codechef] Beautiful Permutation
    传送门以此纪念我场切的dp。这种计数的类型一看就很dp的样子。考场上一开始设的dp状态是\(dp_{i,j,k_1,k_2,0/1}\)表示将前\(i\)个数分为\(j\)段,放了\(k_1\)个偶数,\(k_2\)个奇数,当前段为偶数段或奇数段的方案数。考虑如何转移,记\(cnt_0\)表示序列中可填入的偶数......
  • Codeforces Round 892 (Div. 2)题解记录
    题目链接:https://codeforces.com/contest/1859A.UnitedWeStand选最大的数即可注意题目输出格式 #include<iostream> #include<string.h> #include<map> #include<vector> #include<set> #include<unordered_set> #include<stack> #incl......
  • P5025 [SNOI2017] 炸弹 题解
    题意link.题解一个好想一点的正解。考虑到可能连锁爆炸,我们不能通过一个单纯的二分来解决问题。考虑dp。记\(f(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标小于它的点。\(g(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标大于它的点。我们以\(f\)为例,\(g\)可以通......
  • AT_nikkei2019_2_qual_c 题解
    blog。不会做结论题,怎么办???不会做结论题,怎么办???不会做结论题,怎么办???不妨对\(b\)排序,将\(a\)对应到相应的位置。那么题目有两个条件:#1:\(\foralla_i\leb_i\)。#2:操作限制。注意到\(n-1\)次操作就能完成对\(a\)排序。所以用\(n-2\)次操作可以将\(a\)变成一个Almos......
  • P9351 [JOI 2023 Final] Maze 题解
    Description给定一张\(R\timesC\)的地图,其中.可以走,而#不能走。一次操作可以将\(N\timesN\)的正方形范围内所有点变成.,给定起点和终点,求最少需要几次操作使得起点和终点连通(只能上下左右移动)。\(R\timesC\le6\times10^6\),\(N\leR\leC\)。Solution先考虑怎么......