https://codeforc.es/contest/1194/problem/F

下面是错的。

看起来有点概率dp的感觉?

给你T秒钟时间,你要按顺序处理总共n个事件,每个事件处理花费的时间是ti秒钟,有一半的概率失手导致多花1秒钟。求T时间内处理完事情的总数的期望。

处理完第1个事件,有0.5概率花t1,有0.5概率花t1+1。

处理完第2个事件,有0.25概率花t1+t2,有0.5概率花t1+t2+1,有0.25概率花t1+t2+2。

处理完第3个事件,有0.125概率花t1+t2+t3,有0.375概率花t1+t2+t3+1,有0.375概率花t1+t2+t3+2,有0.125概率花t1+t2+t3+3。


一开始的思路不对,一开始是按“最后一个结束的元素”来分类,这样子导致非常难计算,应该独立算每个元素的贡献概率。


答案\(E=\sum\limits_{i=1}^{n}P(i)\),\(P(i)\)表示第\(i\)个元素贡献的概率。在前面的很多个里面这样的概率是1。

先累计就算每一次都失手还是能做完的前面的若干个。记第一个不一定能够做完的为x。


第一步,统计结束于\(x\)的,失手次数的上限\(d_x\)不能超过\(x\),也要满足\(pre_x+d_x<=T\),即不能超过\(T-pre_x\)。还要保证最后下一个元素\(x+1\)不能被选到吗?其实并不需要这么做,只要在选下一个的时候加上就可以了。

故\(d_x=min(x,T-pre_x)\)。

失手\([0,d_x]\)次会导致贡献第\(x\),这样的贡献是

\(P(x)=(\frac{1}{2})^{x}\sum\limits_{i=0}^{d_x}C_x^i\)


第二步,统计结束于\(x+1\)的,失手次数\(d_{x+1}\)不能超过\(x+1\),也要满足\(pre_{x+1}+d_{x+1}<=T\),即不能超过\(T-pre_{x+1}\)。

\(d_{x+1}=min(x+1,T-pre_{x+1})\)

失手\([0,d_{x+1}]\)次会导致贡献\(x+1\),这样的贡献是

\(P(x+1)=(\frac{1}{2})^{x+1}\sum\limits_{i=0}^{d_{x+1}}C_{x+1}^i\)


最后是一个奇怪的效率问题了。应该也是这道题第二值得学习的地方(第一值得学习的是统计的思路)。

第一个是要注意到组合数的一个变形:

\(C_n^k+C_{n}^{k+1}=C_{n+1}^{k+1}\),也就是按第\(n+1\)个元素有没有被选进这\(k+1\)个元素分类。

所以

\(\sum\limits_{i=0}^{k+1}C_{n+1}^i=C_{n}^{k+1}+C_{n}^{k}+C_{n}^{k}+C_{n}^{k-1}+...+C_{n}^{1}+C_{n}^{0}+C_{n}^{0}\)

也就是:

\(\sum\limits_{i=0}^{k+1}C_{n+1}^i=C_{n}^{k+1}+2*\sum\limits_{i=0}^{k}C_{n}^i\)

第二个是要注意到\(d_{x+1}<=d_{x}+1\),这不是很显然吗,多一件事情肯定要花多至少1秒去处理,就必须少失误一次?这个东西可以保证,上标是单调下降的。

所以可以O(n)转移出所有需要的组合数。因为上下标都是单调的。


还是有了两处溢出错误以及一个T==0也是合法情况的问题。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int mod = 1e9 + 7;
const int inv2 = (mod + 1) >> 1; int n, curn, curk;
ll T, sigmaC, E, inv2x; const int MAXN = 2e5; ll inv[MAXN + 5], fac[MAXN + 5], invfac[MAXN + 5]; void init_inv(int n = MAXN) {
inv[1] = 1;
for(int i = 2; i <= n; i++) {
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
}
} void init_fac_invfac(int n = MAXN) {
init_inv(n);
fac[0] = 1, invfac[0] = 1;
for(int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i % mod;
invfac[i] = invfac[i - 1] * inv[i] % mod;
}
} inline ll C(ll n, ll m) {
if(n < m)
return 0;
return fac[n] * invfac[n - m] % mod * invfac[m] % mod;
} int t[200005];
ll pret[200005]; void calc_sigmaC(int x) {
ll tmp = 0;
int dx = min((ll)x, T - pret[x]);
for(int i = 0; i <= dx; i++) {
tmp += C(x, i);
if(tmp>=mod)
tmp-=mod;
}
sigmaC = tmp;
curn = x;
curk = dx;
} void next_sigmaC(int nextx) {
int dx1 = min((ll)nextx, T - pret[nextx]);
ll tmp = sigmaC;
tmp = 2ll * tmp % mod;
tmp = (tmp + C(curn, curk + 1)) % mod;
curn++;
curk++;
while(curk > dx1) {
tmp = (tmp + mod - C(curn, curk)) % mod;
curk--;
}
sigmaC = tmp;
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
init_fac_invfac();
while(~scanf("%d%lld", &n, &T)) {
pret[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &t[i]);
pret[i] = pret[i - 1] + t[i];
}
E = 0;
inv2x = inv2; //与x配对的sigmaC的系数
int x = 1;
while(x <= n && pret[x] + x <= T) {
x++;
E++;
inv2x = (inv2x * inv2) % mod;
}
//x现在是第一个不一定可以的
if(x <= n) {
calc_sigmaC(x);
for(; x <= n; x++) {
E = (E + inv2x * sigmaC % mod) % mod;
if(T - pret[x + 1] < 0)
break;
next_sigmaC(x + 1); inv2x = (inv2x * inv2) % mod;
}
}
printf("%lld\n", E);
}
}

需要学习的是分类统计的思路,以及组合数直接转移的思想。

Codeforces - 1194F - Crossword Expert - 组合数学的更多相关文章

  1. Codeforces 1194F. Crossword Expert

    传送门 考虑每一个位置的期望贡献 $P[i]$ 对于第 $k$ 个位置,设 $sum=\sum_{i=1}^{k}t[k]$,那么 $T-sum$ 即为用最短时间完成完位置 $k$ 后多出来的空闲时间 ...

  2. Crossword Expert CodeForces - 1194F (期望)

    大意: $n$个题, 按照第$i$题随机$t_i$或$t_i+1$秒钟完成, 最多做$T$秒, 求做题数期望. 期望转为做题数$\ge x$的方案数之和最后再除以总方案数 这是因为$\sum\limi ...

  3. codeforces 1194F (组合数学)

    Codeforces 11194F (组合数学) 传送门:https://codeforces.com/contest/1194/problem/F 题意: 你有n个事件,你需要按照1~n的顺序完成这 ...

  4. CF1194F Crossword Expert(数论,组合数学)

    不难的一题.不知道为什么能 $2500$…… 不过场上推错了一直不会优化…… 首先考虑 $f_i$ 表示恰好做完前 $i$ 道题的概率. 这样很难算.修改一下,$f_i$ 表示做完至少 $i$ 道题的 ...

  5. Codeforces 1090B - LaTeX Expert - [字符串模拟][2018-2019 Russia Open High School Programming Contest Problem B]

    题目链接:https://codeforces.com/contest/1090/problem/B Examplesstandard input The most famous characters ...

  6. Codeforces 995F Cowmpany Cowmpensation - 组合数学

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个棵$n$个点的有根树和整数$D$,给这$n$个点标号,要求每个节点的标号是正整数,且不超过父节点的标号,根节点的标号不得超过D. 很容 ...

  7. Codeforces 40E Number Table - 组合数学

    题目传送门 传送门I 传送门II 题目大意 给定一个$n\times m$的网格,每个格子上要么填$1$,要么填$-1$,有$k$个位置上的数是已经填好的,其他位置都是空的.问有多少种填法使得任意一行 ...

  8. Codeforces 37D Lesson Timetable - 组合数学 - 动态规划

    题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...

  9. Codeforces 711D Directed Roads - 组合数学

    ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it co ...

随机推荐

  1. Linux系统Docker启动问题Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service"

    在Liunx中使用Docker, 注: Liunx使用的是在虚拟机下的centOS7版本在刚开始安装Docker时没有任何错误, 但是在后续的docker启动过程中, 出现以下问题: [root@zk ...

  2. c++ sizeof的实现

    c++中的sizeof,可以通过以下宏定义实现. #include <stdio.h> #define sizeof_T(T) ((size_t)((T*)0+1)) ///求类型的大小 ...

  3. 树——sum-root-to-leaf-numbers(根到叶节点数字之和)

    问题: Given a binary tree containing digits from0-9only, each root-to-leaf path could represent a numb ...

  4. 【Database】Mysql分布式集群学习笔记

    一.sql 的基本操作 (2018年11月29日,笔记) (1)数据库相关操作 创建数据库.查看数据库.删除数据库 #. 创建数据库 create database mytest default ch ...

  5. bzoj3589 动态树 树链剖分+容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3589 题解 事件 \(0\) 不需要说,直接做就可以了. 事件 \(1\) 的话,考虑如果直接 ...

  6. Jenkins配置git/github 插件的ssh key

    参考来源:http://jingyan.baidu.com/article/a65957f4f0acc624e67f9bc1.html 方式一:本地需要生成公私钥文件,git/github中新建ssh ...

  7. BZOJ 3963: [WF2011]MachineWorks 斜率优化 + splay动态维护凸包

    Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先进的机械设备生产先进的机器.原来的那一台生产机器已经坏了,所以 ...

  8. "C++ Primer Plus" is WAY FUCKING BETTER than "C++ Primer" (For Beginners)!!!

    再看到给初学C++的人推荐C++ Primer的我就要揍人了,真的! 被他妈这帮装逼犯给误导了,耽误了无数的功夫! 就是听这帮傻逼的谣言,说C++ Primer讲解更深入什么的,初学也应该啃这本书,老 ...

  9. [CSP-S模拟测试]:旋转子段(数学)

    题目描述 $ZYL$有$N$张牌编号分别为$1,2,...,N$.他把这$N$张牌打乱排成一排,然后他要做一次旋转使得旋转后固定点尽可能多.如果第$i$个位置的牌的编号为$i$,我们就称之为固定点.旋 ...

  10. 关于CSS你应该知道的基础知识 - 样式应用篇

    上一篇简单总结了一下选择器,如果一个元素被多个选择器选中,元素的样式就会以级联方式被应用到.要搞清最终那个样式被应用到元素上了,首先要明白引用CSS代码的几种方式. CSS代码引用方式 如何应用CSS ...