题意

LOJ #2541. 「PKUWC 2018」猎人杀

题解

一道及其巧妙的题 , 参考了一下这位大佬的博客 ...

令 \(\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\) 就行了 .

\[\displaystyle f_{i,j} \to f_{i+1,j} ; -f_{i,j} \to f_{i+1,j+w_i}
\]

不难发现这个是个多项式乘法 ...

又由于多项式乘法有交换律和结合律 , 直接每次挑 \(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优化)的更多相关文章

  1. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  2. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

  3. LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)

    写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...

  4. LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)

    题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...

  5. LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)

    题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...

  6. LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP

    题目:https://loj.ac/problem/3124 看了题解:https://www.cnblogs.com/Itst/p/10883880.html 先考虑外向树. 考虑分母是 \( \s ...

  7. loj 2778「BalticOI 2018」基因工程

    loj luogu 这题和NOI那道向量内积一个套路 首先考虑求两行的不同元素个数,可以转化成一个行向量\(a\)和列向量\(b\)相乘得到一个值.如果只有\(A,C\)两种字符,那么令对应权值\(A ...

  8. 「PKUWC 2018」Minimax

    传送门:Here 一道线段树合并好题 如果要维护点$ x$的信息,相当于合并$ x$的两棵子树 对于这题显然有:任何叶子节点的权值都可能出现在其祖先上 因而我们只需要在线段树合并的时候维护概率即可 我 ...

  9. loj2538 「PKUWC 2018」Slay the Spire

    pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...

随机推荐

  1. Qt小项目之串口助手控制LED

    Qt小项目之串口助手控制LED 前言 最近刚学了一点Qt开发上位机,尝试着做个小软件练练手.查找了很多资料,做了一个简单的串口助手,可以实现串口基本发送和接收功能,支持中文显示,还可以控制STM32开 ...

  2. ABP从入门到精通(5):.扩展国际化语言资源

    ABP的有些组件使用的该组件自带的语言包资源,所以在有些时候会因为我们当前使用的语言对应的语言包不全,而造成日志一直记录WARN.ABP给我们提供了扩展语言包资源的接口,可以解决这个问题. 以下示例代 ...

  3. Spring Boot 2.0 版的开源项目云收藏来了!

    给大家聊一聊云收藏从 Spring Boot 1.0 升级到 2.0 所踩的坑 先给大家晒一下云收藏的几个数据,作为一个 Spring Boot 的开源项目(https://github.com/cl ...

  4. item 10: 比起unscoped enum更偏爱scoped enum

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 一般情况下,在花括号中声明一个name(包括变量名,函数名),这个 ...

  5. 【转】Git版本控制软件从入门到精通学习手册

    GIT 学习手册简介 本站为 Git 学习参考手册.目的是为学习与记忆 Git 使用中最重要.最普遍的命令提供快速翻阅. 这些命令以你可能需要的操作类型划分,并且将提供日常使用中需要的一些常用的命令以 ...

  6. python 批量下载图片

    #coding=utf-8import re,sysimport urllib def getHtml(url): page = urllib.urlopen(url) html = page.rea ...

  7. hdu 3038 给区间和,算出多少是错的

    参考博客 How Many Answers Are Wrong Problem Description TT and FF are ... friends. Uh... very very good ...

  8. 作业20171102 beta1 成绩

    申诉 对成绩有疑问或不同意见的同学,请在群里[@杨贵福]. 申诉时间截止2017年12月12日 17:00. 成绩 scrum01 scrum02 scrum03 scrum04 scrum05 sc ...

  9. linux及安全第四周总结

    学习内容:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 一.用户态.内核态 权限分级——为了系统本身更稳定,使系统不宜崩溃.(并不是所有程序员缩写的代码都很健壮!!) x86 CP ...

  10. 20145221 《Java程序设计》实验报告四:Android开发基础

    20145221 <Java程序设计>实验报告四:Android开发基础 实验要求 基于Android Studio开发简单的Android应用并部署测试; 了解Android组件.布局管 ...