LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意
题解
一道及其巧妙的题 , 参考了一下这位大佬的博客 ...
令 \(\displaystyle A = \sum_{i=1}^{n} w_i\) , \(B\) 是已死猎人的 \(w_i\) 的总和 , \(P_i\) 是 \(i\) 当前要被杀死的概率 ... (抄博客咯)
不难有 \(\displaystyle P_i = \frac{w_i}{A-B} \tag{1}\)
如果 不考虑猎人死没死 , 都能被当做目标 qwq (鞭尸) 也就是算进去概率 ...
那么也会有 \(\displaystyle P_i = \frac{B}{A} P_i + \frac{w_i}{A} \tag{2}\)
这个是为什么呢 ... 因为假设打到它 那么就是死了 , 如果打到了死的目标 , 那么这把又会重新来过 , 但他死的概率还是没变 ... (类似于有一些期望题中的高斯消元)
发现 \((2)\) 移项后就得到了 \((1) ~ !!!!\) 这个就很巧妙啦 ~ 也就是说 按第二种来算也可以算出正确的结果 .
然后我们考虑容斥 , 枚举在 \(1\) 号后面死的人 , 然后令 \(S\) 为枚举到的人的 \(w_i\) 之和 , 人数为 \(t\) . 那么意味着 \(1\) 号的位置至多是 \(n - t\) 位 .
不难发现答案就是 $$\displaystyle ans = (-1)^t \sum_{i=0}^{\infty} (1-\frac{S+w_1}{A})^i\frac{w_1}{A}$$ .
这个代入前面的式子就可以得到了 . 这里虽然算的是无限概率 , 但是一个收敛的无限等比数列 , 我们用常规的作差法就可算出来了 .
令\(\displaystyle T = \sum_{i=0}^{\infty} (1-\frac{S+w_1}{A})^i \tag{3}\)
则又有\(\displaystyle (1-\frac{S+w_1}{A})T=\sum_{i=1}^{\infty} (1-\frac{S+w_1}{A})^i \tag{4}\)
让 \((3) - (4)\) 就可以得到
\[\displaystyle \frac{S+w_1}{A} T = (1-\frac{S+w_1}{A})^0=1
\]\[\displaystyle \therefore T=\frac{A}{S+w_1}
\]\[\displaystyle \therefore ans=(-1)^t\frac{w_1}{S+w_1}
\]
啊 多么美妙的一个式子啊 qwq
然后直接算每个 \(S\) 前面的系数就行了 .
朴素 dp 就是 令 \(f_{i,j}\) 为到第 \(i\) 个总和为 \(j\) 的系数和 . 每次有两种决策 , 一种是选第 \(i\) 个 另一种是不选 .
那么很容易发现第一种加上去的时候奇偶性改变 , 乘上 \(-1\) 就行了 .
\]
不难发现这个是个多项式乘法 ...
又由于多项式乘法有交换律和结合律 , 直接每次挑 \(size\) 最小的两个合并就行了 .
令 \(\displaystyle q=\sum_{i=1}^{n} w_i\) 时间复杂度就是 \(O(q \log q \log n)\) 可以通过此题...
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("2541.in", "r", stdin);
freopen ("2541.out", "w", stdout);
#endif
}
typedef long long ll;
const int Mod = 998244353;
ll fpm(ll x, int power) {
ll res = 1;
for (; power; power >>= 1, (x *= x) %= Mod)
if (power & 1) (res *= x) %= Mod;
return res;
}
const int Maxn = (1 << 20) + 5;
struct Number_Theoretical_Transform {
int n, n1, n2, m;
ll pow3[Maxn], invpow3[Maxn];
inline void Init(int maxn) {
for (int i = 1; i <= maxn; i <<= 1) {
pow3[i] = fpm(3, (Mod - 1) / i);
invpow3[i] = fpm(pow3[i], Mod - 2);
}
}
int rev[Maxn];
void NTT(ll P[], int opt) {
For (i, 0, n - 1) if (i < rev[i]) swap(P[i], P[rev[i]]);
for (int i = 2; i <= n; i <<= 1) {
int p = i / 2;
ll Wi = opt == 1 ? pow3[i] : invpow3[i];
for (int j = 0; j < n; j += i) {
ll x = 1;
for (int k = 0; k < p; ++ k, (x *= Wi) %= Mod) {
ll u = P[j + k], v = x * P[j + k + p] % Mod;
P[j + k] = (u + v) % Mod;
P[j + k + p] = (u - v + Mod) % Mod;
}
}
}
if (opt == -1) {
ll invn = fpm(n, Mod - 2);
For (i, 0, n - 1) (P[i] *= invn) %= Mod;
}
}
ll A[Maxn], B[Maxn];
inline vector<int> Mult(vector<int> a, vector<int> b) {
n1 = (int)a.size() - 1; n2 = (int)b.size() - 1; m = n1 + n2;
For (i, 0, n1) A[i] = a[i]; For (i, 0, n2) B[i] = b[i];
int cnt = 0; for (n = 1; n <= m; n <<= 1) ++ cnt;
For (i, 1, n) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (cnt - 1));
For (i, n1 + 1, n) A[i] = 0; For (i, n2 + 1, n) B[i] = 0;
NTT(A, 1); NTT(B, 1);
For (i, 0, n - 1) (A[i] *= B[i]) %= Mod;
NTT(A, - 1);
vector<int> res; res.resize(m + 1); For (i, 0, m) res[i] = A[i];
return res;
}
} T;
const int N = 100010;
int n, dp[2][N], w[N], cur, w1;
struct Seq {
vector<int> V;
inline bool operator < (const Seq &rhs) const {
return (int)V.size() > (int)rhs.V.size();
}
} ;
priority_queue<Seq, vector<Seq> > P;
void Out(vector<int> A) {
For (i, 0, A.size() - 1)
printf ("%d%c", A[i], i == iend ? '\n' : ' ');
}
int main () {
File(); T.Init(1 << 20);
n = read() - 1; w1 = read();
int tot = 0;
For (i, 1, n) w[i] = read(), tot += w[i];
For (i, 1, n) {
vector<int> now;
now.resize(w[i] + 1);
now[0] = 1; now[w[i]] = Mod - 1;
P.push((Seq) {now});
}
while (P.size() > 1) {
Seq a = P.top(); P.pop();
Seq b = P.top(); P.pop();
P.push((Seq) {T.Mult(a.V, b.V)});
}
Seq res = P.top();
int ans = 0;
For (i, 0, res.V.size() - 1) {
ans += 1ll * res.V[i] * w1 % Mod * fpm(i + w1, Mod - 2) % Mod;
ans = (ans % Mod + Mod) % Mod;
}
printf ("%d\n", ans);
return 0;
}
LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)的更多相关文章
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)
写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...
- LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)
题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...
- LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)
题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...
- LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP
题目:https://loj.ac/problem/3124 看了题解:https://www.cnblogs.com/Itst/p/10883880.html 先考虑外向树. 考虑分母是 \( \s ...
- loj 2778「BalticOI 2018」基因工程
loj luogu 这题和NOI那道向量内积一个套路 首先考虑求两行的不同元素个数,可以转化成一个行向量\(a\)和列向量\(b\)相乘得到一个值.如果只有\(A,C\)两种字符,那么令对应权值\(A ...
- 「PKUWC 2018」Minimax
传送门:Here 一道线段树合并好题 如果要维护点$ x$的信息,相当于合并$ x$的两棵子树 对于这题显然有:任何叶子节点的权值都可能出现在其祖先上 因而我们只需要在线段树合并的时候维护概率即可 我 ...
- loj2538 「PKUWC 2018」Slay the Spire
pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...
随机推荐
- EF Core中DbContext可以被Dispose多次
我们知道,在EF Core中DbContext用完后要记得调用Dispose方法释放资源.但是其实DbContext可以多次调用Dispose方法,虽然只有第一次Dispose会起作用,但是DbCon ...
- CF915G Coprime Arrays 莫比乌斯反演、差分、前缀和
传送门 差分是真心人类智慧--完全不会 这么经典的式子肯定考虑莫比乌斯反演,不难得到\(b_k = \sum\limits_{i=1}^k \mu(i) \lfloor\frac{k}{i} \rfl ...
- kettle学习笔记——插件的安装与使用
一.概述 暂略 二.ODPS插件 https://yq.aliyun.com/articles/68911
- EZ 2018 06 17 NOIP2018 模拟赛(十九)
这次的题目难得的水,但是由于许多哲学的原因,第二题题意表述很迷. 然后是真的猜题意了搞了. 不过这样都可以涨Rating我也是服了. Upt:链接莫名又消失了 A. 「NOIP2017模拟赛11.03 ...
- LOJ #6062. 「2017 山东一轮集训 Day2」Pair
这是Lowest JN dalao昨天上课讲的一道神题其实是水题啦 题意很简单,我们也很容易建模转化出一个奇怪的东西 首先我们对b进行sort,然后我们就可以通过二分来判断出这个数可以和哪些数配对 然 ...
- Coolest Ski Route-不定起点和终点----在有向变的情况下---求最长路
这题最开始给你了N个点,M条边,边是单向边,问不指定起点和终点,最长路是什么??? 脑补一下,不定起点和终点的最短路,用弗洛伊德算法搞一搞,但是...那个垃圾算法的复杂度是N^3的,但是这个算法的M高 ...
- M2postmortem
设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 答:我们的软件主要解决信息提取的问题.定义清晰:要提取的内容包括于计算机科学相关内容的标题.作者. ...
- SPRINT四则运算(第二天)
1.小组成员: 李豌湄:master 江丹仪:产品负责人 2.现状: a.已经下载APP分析他们的界面.优缺点和闪光点 b.已改进代码添加功能 3.任务认领: 完成任务的第一个模块: a.下载五个类 ...
- eclipse webproject activiti
https://stackoverflow.com/questions/42858723/activiti-eclipse-maven-project-to-dynamic-web-project-a ...
- Delphi7通过superobject解析JSON
1.通过delphi程序访问PHP事先写好的webservice(查询功能),webservice返回json格式数据. 2.通过superobject读取json数据 得到效果如下: //深层级的访 ...