LOJ#2541 猎人杀
解:step1:猎人死了之后不下台,而是继续开枪,这样分母不变......
然后容斥,枚举猎人集合s,钦定他们在1之后死。定义打到1的时候结束,枚举游戏在i轮时结束。
发现式子是一个1 + x + x2 + x3 + ... = 1 / (1 - x)
但是枚举子集不现实,发现值域很小,我们用小Z的礼物的套路,考虑计算每个值的容斥系数是多少。
然后就NTT加速了。预处理逆元卡常。
#include <bits/stdc++.h> typedef long long LL;
typedef std::vector<int> Poly; inline void read(int &x) {
x = ;
char c = getchar();
while(c < '' || c > '') c = getchar();
while(c >= '' && c <= '') {
x = x * + c - ;
c = getchar();
}
return;
} const int N = , MO = ; int A[N << ], B[N << ];
int r[N << ], n, w[N], inv[N]; inline int qpow(int a, int b) {
a = (a % MO + MO) % MO;
int ans = ;
while(b) {
if(b & ) ans = 1ll * ans * a % MO;
a = 1ll * a * a % MO;
b = b >> ;
}
return ans;
} inline void prework(int n) {
static int R = ;
if(R == n) return;
R = n;
int lm = ;
while(( << lm) < n) lm++;
for(register int i = ; i < n; i++) r[i] = (r[i >> ] >> ) | ((i & ) << (lm - ));
return;
} inline void NTT(int *a, int n, int f) {
prework(n);
for(int i = ; i < n; i++) {
if(i < r[i]) std::swap(a[i], a[r[i]]);
}
for(register int len = ; len < n; len <<= ) {
int Wn = qpow(, (MO - ) / (len << ));
if(f == -) Wn = qpow(Wn, MO - );
for(register int i = ; i < n; i += (len << )) {
int w = ;
for(register int j = ; j < len; j++) {
int t = 1ll * a[i + len + j] * w % MO;
a[i + len + j] = (a[i + j] - t) % MO;
a[i + j] = (a[i + j] + t) % MO;
w = 1ll * w * Wn % MO;
}
}
}
if(f == -) {
LL inv = qpow(n, MO - );
for(int i = ; i < n; i++) {
a[i] = 1ll * a[i] * inv % MO;
}
}
return;
} inline Poly mul(const Poly &a, const Poly &b) {
int na = a.size(), nb = b.size(), n = na + nb - , len = ;
while(len < n) len <<= ;
for(register int i = ; i < na; i++) A[i] = a[i];
for(register int i = ; i < nb; i++) B[i] = b[i];
memset(A + na, , (len - na) * sizeof(LL));
memset(B + nb, , (len - nb) * sizeof(LL));
NTT(A, len, ); NTT(B, len, );
for(register int i = ; i < len; i++) A[i] = 1ll * A[i] * B[i] % MO;
NTT(A, len, -);
Poly ans(n);
for(register int i = ; i < n; i++) ans[i] = A[i];
return ans;
} Poly solve(int l, int r) {
if(l == r) {
Poly a(w[r] + );
a[] = ; a[w[r]] = -;
return a;
}
int mid = (l + r) >> ;
return mul(solve(l, mid), solve(mid + , r));
} int main() {
int sum = ;
read(n);
for(register int i = ; i <= n; i++) {
read(w[i]);
sum += w[i];
} inv[] = inv[] = ;
for(int i = ; i <= sum; i++) {
inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO;
} std::sort(w + , w + n + );
Poly a = solve(, n); int m = a.size();
int ans = ;
for(register int i = ; i < m; i++) {
ans = (ans + 1ll * a[i] * inv[w[] + i] % MO) % MO;
}
ans = 1ll * ans * w[] % MO;
printf("%d\n", (ans + MO) % MO);
return ;
}
AC代码
LOJ#2541 猎人杀的更多相关文章
- LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...
- LOJ #2541「PKUWC2018」猎人杀
这样$ PKUWC$就只差一道斗地主了 假装补题补完了吧..... 这题还是挺巧妙的啊...... LOJ # 2541 题意 每个人有一个嘲讽值$a_i$,每次杀死一个人,杀死某人的概率为$ \fr ...
- 【杂题】[LibreOJ 2541] 【PKUWC2018】猎人杀【生成函数】【概率与期望】
Description 猎人杀是一款风靡一时的游戏"狼人杀"的民间版本,他的规则是这样的: 一开始有 n个猎人,第 i 个猎人有仇恨度 wi.每个猎人只有一个固定的技能:死亡后必须 ...
- 【LOJ2541】【PKUWC2018】猎人杀(容斥,FFT)
[LOJ2541][PKUWC2018]猎人杀(容斥,FFT) 题面 LOJ 题解 这题好神仙啊. 直接考虑概率很麻烦,因为分母总是在变化. 但是,如果一个人死亡之后,我们不让他离场,假装给他打一个标 ...
- 「PKUWC2018」猎人杀
「PKUWC2018」猎人杀 解题思路 首先有一个很妙的结论是问题可以转化为已经死掉的猎人继续算在概率里面,每一轮一直开枪直到射死一个之前没死的猎人为止. 证明,设所有猎人的概率之和为 \(W\) , ...
- LOJ 2541 「PKUWC2018」猎人杀——思路+概率+容斥+分治
题目:https://loj.ac/problem/2541 看了题解才会……有三点很巧妙. 1.分母如果变动,就很不好.所以考虑把操作改成 “已经选过的人仍然按 \( w_i \) 的概率被选,但是 ...
- 【LOJ】#2541. 「PKUWC2018」猎人杀
题解 一道神仙的题>< 我们毙掉一个人后总的w的和会减少,怎么看怎么像指数算法 然而,我们可以容斥-- 设\(\sum_{i = 1}^{n} w_{i} = Sum\) 我们把问题转化一 ...
- loj#2541. 「PKUWC2018」猎人杀
传送门 思路太清奇了-- 考虑容斥,即枚举至少有哪几个是在\(1\)号之后被杀的.设\(A=\sum_{i=1}^nw_i\),\(S\)为那几个在\(1\)号之后被杀的人的\(w\)之和.关于杀了人 ...
- [LOJ2541]「PKUWC2018」猎人杀
loj description 有\(n\)个猎人,每个猎人有一个仇恨度\(w_i\),每个猎人死后会开一枪打死一个还活着的猎人,打中每个猎人的概率与他的仇恨度成正比. 现在你开了第一枪,打死每个猎人 ...
随机推荐
- (C/C++)区别:数组与指针,指针与引用
1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型 ...
- python之路--面向对象-成员
一 . 成员 在类中你能写的所有内容都是类的成员 class 类名: # 方法 def__init__(self, 参数1, 参数2...): # 属性变量 self.属性1 = 参数1 self.属 ...
- echo显示颜色
如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ [;;34m hello aaron \[0m”
- vue 條件語句
條件判斷使用v-if.v-else-if.v-else. v-show
- 虚拟机linux系统明明已经安装了ubuntu,但是每次重新进入就又是选择安装界面
本文转载:https://blog.csdn.net/weixin_41522164/article/details/82814375
- Linux下4个查找命令which、whereis、locate、find的总结
(1)which [-a] cmdname1 cmdname2 ...... 作用:locate a command,从环境变量PATH中,定位/返回与指定名字相匹配的可执行文件所在的路径 ...
- MongoDB学习目录
前面的话 为了能够使用NodeJS实现后端,MongoDB——这个NodeJS标配的数据库就不得不学.小火柴将MongoDB数据库的学习记录整理如下 基础 基础操作 数据类型 文档操作 索引 索引构建 ...
- Android PowerManager电源管理(Android N )
./frameworks/base/core/java/android/os/PowerManager.java该类提供给Application访问电源相关接口. 它的内部类WakeLock是定义的唤 ...
- load加载层-layui
加载样式 //eg1 var index = layer.load(); //eg2 var index = layer.load(1); //换了种风格 //eg3 var index = laye ...
- IntelliJ cannot log in to GitHub上传github报错解决
重装系统,新装的Intellij IDEA上新建的项目上传github失败,报错: invalid authentication token ... 此处多为本地git用户的用户名/邮箱,与之前设置的 ...