Codeforces - 1194F - Crossword Expert - 组合数学
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 - 组合数学的更多相关文章
- Codeforces 1194F. Crossword Expert
传送门 考虑每一个位置的期望贡献 $P[i]$ 对于第 $k$ 个位置,设 $sum=\sum_{i=1}^{k}t[k]$,那么 $T-sum$ 即为用最短时间完成完位置 $k$ 后多出来的空闲时间 ...
- Crossword Expert CodeForces - 1194F (期望)
大意: $n$个题, 按照第$i$题随机$t_i$或$t_i+1$秒钟完成, 最多做$T$秒, 求做题数期望. 期望转为做题数$\ge x$的方案数之和最后再除以总方案数 这是因为$\sum\limi ...
- codeforces 1194F (组合数学)
Codeforces 11194F (组合数学) 传送门:https://codeforces.com/contest/1194/problem/F 题意: 你有n个事件,你需要按照1~n的顺序完成这 ...
- CF1194F Crossword Expert(数论,组合数学)
不难的一题.不知道为什么能 $2500$…… 不过场上推错了一直不会优化…… 首先考虑 $f_i$ 表示恰好做完前 $i$ 道题的概率. 这样很难算.修改一下,$f_i$ 表示做完至少 $i$ 道题的 ...
- 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 ...
- Codeforces 995F Cowmpany Cowmpensation - 组合数学
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个棵$n$个点的有根树和整数$D$,给这$n$个点标号,要求每个节点的标号是正整数,且不超过父节点的标号,根节点的标号不得超过D. 很容 ...
- Codeforces 40E Number Table - 组合数学
题目传送门 传送门I 传送门II 题目大意 给定一个$n\times m$的网格,每个格子上要么填$1$,要么填$-1$,有$k$个位置上的数是已经填好的,其他位置都是空的.问有多少种填法使得任意一行 ...
- Codeforces 37D Lesson Timetable - 组合数学 - 动态规划
题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...
- Codeforces 711D Directed Roads - 组合数学
ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it co ...
随机推荐
- 高精乘(fft板子
哇..fft的原理真的是不太好懂,看了好久许多细节还是不太清楚,但感觉本质就是用了单位根的性质. https://www.luogu.org/problem/P1919 #include<cst ...
- Vue.js 技术揭秘学习 (3) render
Vue 的 _render 方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node ,返回的是一个VNode 在 Vue 的官方文档中介绍了 render 函数的第一个参数是 createE ...
- BitMap位图
BitMap位图算法https://blog.csdn.net/varyall/article/details/79662029 常见面试题 题1:在2.5亿个整数找出不重复的整数,内存不足以容纳着2 ...
- layer-框架使用修改部分
关于框架中js调子方法出错的处理 top.layer.open({ id: options.id, type: 2, shade: options.shade, title: options.titl ...
- 【leetcode】447. Number of Boomerangs
题目如下: 解题思路:我首先用来时间复杂度是O(n^3)的解法,会判定为超时:后来尝试O(n^2)的解法,可以被AC.对于任意一个点,我们都可以计算出它与其余点的距离,使用一个字典保存每个距离的点的数 ...
- SystemUI分析
SystemUI是安卓的一个系统APP,负责的内容有系统通知栏,状态栏,最近应用程序,锁屏,壁纸,屏保,系统对话框,截屏,录屏等功能. Apk的路径位于/system/priv-app,源码code位 ...
- MaxCompute Studio 使用入门
MaxCompute Studio 是MaxCompute 平台提供的安装在开发者客户端的大数据集成开发环境工具,是一套基于流行的集成开发平台 IntelliJ IDEA 的开发插件,可以帮助您方便地 ...
- Android多线程方案
为主线程减轻负的多线程方案有哪些呢?这些方案分别适合在什么场景下使用? Android系统为我们提供了若干组工具类来帮助解决这个问题. AsyncTask: 为UI线程与工作线程之间进行快速的切换提供 ...
- 观察者模式使用WebForm实现的例子
观察者模式是一种可以描述一对多对象依赖关系的行为模式.当一个对象状态发生变化时,依赖它的其它对象会自动被更新状态.下面这个图展示了观察者模式的层级: 举个例子吧,我们某个报表界面现在有个dashboa ...
- [洛谷P3943]:星空(DP+最短路)
题目传送门 题目背景 命运偷走如果只留下结果, 时间偷走初衷只留下了苦衷.你来过,然后你走后,只留下星空. 题目描述 逃不掉的那一天还是来了,小$F$看着夜空发呆.天上空荡荡的,没有一颗星星——大概是 ...