Codeforces Round #604
Beautiful Regional Contest
题目链接 http://codeforces.com/contest/1264/problem/A
题意
给出区域赛中 N 支队伍做出的题数,在一定规则下发奖时,金银铜牌奖牌数总和的最大值。
要求:
- 合法方案中每种奖牌至少一个
- 金牌数严格少于银牌和铜牌数,银牌和铜牌数间没有要求
- 金牌队伍解题数必须严格大于银牌队伍解题数,银铜、铜铁同理。
- 奖牌总数和不能超过队伍总数的一半(21支队伍时奖牌数至多10,26支队伍将牌至多13)。
题解
首先根据 要求4,去除一定不可能得奖的后一半人。
因为 要求2 只要求银铜的奖牌数多于金牌,所以直接使金牌数为最少(解题最多的那些队伍),然后从剩下的队伍中找到足够多的队伍得银牌(前缀和然后二分),剩下得铜牌即可。
注意中间发现无法满足要求时及时结束代码。
代码
/*
* Codeforces Round #604
* Beautiful Regional Contest
*/
#include <cstdio>
#include <algorithm>
using namespace std;
int N;
int ls[400010];
void work() {
scanf("%d", &N);
for (int i = 0; i < N; i++) {
scanf("%d", ls+i);
}
int j, nu;
nu = ls[0];
ls[0] = 1;
j = 0;
for (int i = 1; i < N; i++) {
if (ls[i] == nu) {
ls[j]++;
}
else {
nu = ls[i];
j++;
ls[j] = 1;
}
}
int sm = 0;
for (int i = j; i >= 0; i--) {
sm += ls[i];
if (sm*2 >= N) {
j = i;
break;
}
}
if (j < 3) {
printf("0 0 0\n");
return;
}
for (int i = 1; i < j; i++) {
ls[i] += ls[i-1];
}
int a, b, c;
a = ls[0];
int *it;
it = lower_bound(ls, ls+j, a*2+1);
if (it == ls+j)
a = b = c = 0;
else {
b = *it - a;
c = ls[j-1] - *it;
if (!a || !b || !c || a>=c) {
a = b = c = 0;
}
}
printf("%d %d %d\n", a, b, c);
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
work();
}
return 0;
}
Beautiful Sequence
题目链接 http://codeforces.com/contest/1264/problem/B
题意
给出 0, 1, 2, 3 四种数字的个数 a, b, c, d,要求构造数列,满足相邻数字相差为1。
题解
可以知道 0 只能和 1 相邻,当有多个 0 时,一定是通过 010101 这样的序列消耗掉 0 的,对于 3 同理,通过 232323 消耗。
优先考虑用 1 消耗尽可能多的 0,用 2 消耗尽可能多的 3。
剩下的 1 和 2 一定是通过 212121 的序列消耗的。
根据上述规则构成 010121212323 序列中的三部分 0101 2121 2323。
此外,恰好多出一个 1 和 2 时可以放在开头和结尾形成 1 0101 2121 2323 2。
多出 0 和 3 时,以 0 为例,构成 0101 0 时需要保证没有 2 和 3,因为 2 和 3 都不能接在 0 的后面。
按照如上分析实现代码即可。
实际做题过程中,通过理清思路可以让编码难度直线下降。
当前思路为,优先考虑 01 和 23 成对消耗,然后考虑剩余 12 成对消耗,最后处理多余数字的情况。这是因为成对消耗可以看作是化简问题的过程,处理多余数字是特判的过程。
如果混用这两部分的话,容易出错漏情况。
代码
/*
* Codeforces Round #604
* Beautiful Sequence
*/
#include <cstdio>
#include <algorithm>
using namespace std;
int a, b, c, d;
int main() {
scanf("%d %d %d %d", &a, &b, &c, &d);
int A, B, C, D;
int u;
A = a;
B = b;
C = c;
D = d;
u = min(A, B);
A -= u;
B -= u;
u = min(C, D);
C -= u;
D -= u;
u = min(B, C);
B -= u;
C -= u;
if (A > 1 || B > 1 || C > 1 || D > 1)
goto be;
if ((A && (c||d)) || (D && (a||b)))
goto be;
he:
printf("YES\n");
if (B)
printf("1 ");
u = min(a, b);
for (int i = 0; i < u; i++)
printf("0 1 ");
if (A)
printf("0 ");
u = min(b - min(a, b), c - min(c, d));
for (int i = 0; i < u; i++)
printf("2 1 ");
if (D)
printf("3 ");
u = min(c, d);
for (int i = 0; i < u; i++)
printf("2 3 ");
if (C)
printf("2 ");
printf("\n");
return 0;
be:
printf("NO\n");
return 0;
}
一个思路不够清晰的代码
/*
* Codeforces Round #604
* Beautiful Sequence
*/
#include <cstdio>
#include <algorithm>
using namespace std;
int a, b, c, d;
int main() {
scanf("%d %d %d %d", &a, &b, &c, &d);
int A, B, C, D;
int u;
A = a;
B = b;
C = c;
D = d;
// 从这里开始
u = min(A, B);
A -= u;
B -= u;
u = min(C, D);
C -= u;
D -= u;
if (A > 1 || D > 1)
goto be;
if (A && (c||d))
goto be;
if (D && (a||b))
goto be;
int uBC;
uBC = u = min(B, C);
B -= u;
C -= u;
if (B > 1 || C > 1)
goto be;
// 到这里
he:
printf("YES\n");
if (B)
printf("1 ");
u = min(a, b);
for (int i = 0; i < u; i++)
printf("0 1 ");
if (A)
printf("0 ");
u = uBC;
for (int i = 0; i < u; i++)
printf("2 1 ");
if (D)
printf("3 ");
u = min(c, d);
for (int i = 0; i < u; i++)
printf("2 3 ");
if (C)
printf("2 ");
printf("\n");
return 0;
be:
printf("NO\n");
return 0;
}
Beautiful Mirrors with queries
题目链接 https://codeforces.com/contest/1264/problem/C
题意
N 个节点依次排列,每天尝试通过一个节点,每个节点有 \(P_i\) 的概率通过,下一天尝试第 i+1 个节点,如果没通过,下一天尝试通过前面最近的存档点。
求成功通过最后一个节点需要天数的期望。
Q 次询问,每次给出一个编号 u,修改 u 是否为检查点,并且输出修改后的答案。
1 号节点始终为存档点。
题中 \(P_i\) 以 \(\frac{p_i}{100}\) 的形式给出。
题解
如果没有检查点的修改,显然可以通过如下递推式计算答案,其中 \(F_i\) 表示从起点走到 i 号点需要天数的期望。
\[ F_i = F_{i-1} + P_i*1 + (1-P_i)(F_i+1) \]
在经过了前 \(i-1\) 个节点之后,\(P_i\) 的概率一次尝试并通过,\(1-P_i\)的概率退回存档点重新开始。
或者可以用一个通项公式来求,\(E\) 表示通过全部节点的期望天数。
\[ E = P_1(1+P_2(1+\dots)+(1-P_2)(1+E)) + (1-P_1)(1+E) \]
化简式子:
\[ \begin{aligned}
E =& (P_1 + P_1P_2 +\dots+ P_1\dots P_N)\\
&+[(1-P_1)(1+E) + P_1(1-P_2)(1+E) +\dots+ P_1\dots P_{N-1}(1-P_N)(1+E)]\\
=& (P_1 + P_1P_2 +\dots+ P_1\dots P_N) + (1-P_1\dots P_N)(1+E)\\
=& (1 + P_1 + P_1P_2 +\dots+ P_1\dots P_{N-1}) + (1-P_1\dots P_N)E
\end{aligned} \]
即
\[
E = \frac{A}{B} = \frac{1+P_1+P_1P_2+\dots+P_1\dots P_{N-1}}{P_1P_2\dots P_N}
\]
对于多个检查点的情况,可以发现,检查点分开的两段可以单独处理
即存在 x 号节点是检查点时,可以分别计算 \(E_{1,x-1}\) 和 \(E_{x,N}\) 然后求和就是总答案。
更一般的,有:
\[
E_{u,v} = \frac{A_{u,v}}{B_{u,v}} = \frac{1+P_u+P_uP_{u+1}+\dots+P_u\dots P_{v-1}}{P_uP_{u+1}\dots P_v}
\]
分别计算检查点隔开的每一段即可。
在 a, c 之间添加新的检查点 b 时,删除 (a, c-1),增加 (a, b-1), (b, c-1)。
删除时相反。
可以用 set 直接维护检查点。
代码
/*
* Codeforces Round #604
* Beautiful Mirrors with queries
*/
#include <cstdio>
#include <set>
using namespace std;
#define Nmax 200010
typedef long long LL;
LL MD = 998244353;
LL fpw(LL a, LL b) {
LL ans = 1;
while (b) {
if (b & 1)
ans = ans * a % MD;
a = a * a % MD;
b >>= 1;
}
return ans;
}
inline LL re(LL a) {
return fpw(a, MD - 2);
}
int N, Q;
LL P[Nmax];
LL mt[Nmax];
LL sm[Nmax];
LL ans;
set<int> st;
LL getans(int a, int b) {
LL p;
p = (((sm[b-2]-sm[a-1])%MD+MD)%MD
* re(mt[a-1]) %MD + 1)%MD
* re(mt[b-1]*re(mt[a-1])%MD) %MD;
return p;
}
void init() {
LL hdr;
hdr = re(100);
mt[0] = 1;
sm[0] = 0;
for (int i = 1; i <= N; i++) {
P[i] = P[i] * hdr % MD;
mt[i] = mt[i-1] * P[i] % MD;
sm[i] = sm[i-1] + mt[i] % MD;
}
st.insert(1);
st.insert(N+1);
ans = (sm[N-1]+1)%MD * re(mt[N]) % MD;
}
int main() {
scanf("%d %d", &N, &Q);
for (int i = 1; i <= N; i++) {
scanf("%lld", P+i);
}
init();
int x, y, z;
set<int>::iterator it;
for (int i = 0; i < Q; i++) {
scanf("%d", &x);
if (st.count(x)) {
it = st.find(x);
it--;
y = *it;
it++;
it++;
z = *it;
st.erase(x);
ans = ((ans-getans(y, x))%MD+MD)%MD;
ans = ((ans-getans(x, z))%MD+MD)%MD;
ans = (ans+getans(y, z))%MD;
}
else {
st.insert(x);
it = st.find(x);
it--;
y = *it;
it++;
it++;
z = *it;
ans = ((ans-getans(y, z))%MD+MD)%MD;
ans = (ans+getans(y, x))%MD;
ans = (ans+getans(x, z))%MD;
}
printf("%lld\n", ans);
}
return 0;
}
Codeforces Round #604的更多相关文章
- Codeforces Round #604(Div. 2,
// https://codeforces.com/contest/1265/problem/D /* 感觉像是遍历的思维构造题 有思路就很好做的 可以把该题想象成过山车或者山峰...... */ # ...
- Codeforces Round #604 (Div. 2) E. Beautiful Mirrors
链接: https://codeforces.com/contest/1265/problem/E 题意: Creatnx has n mirrors, numbered from 1 to n. E ...
- Codeforces Round #604 (Div. 2) D. Beautiful Sequence(构造)
链接: https://codeforces.com/contest/1265/problem/D 题意: An integer sequence is called beautiful if the ...
- Codeforces Round #604 (Div. 2) C. Beautiful Regional Contest
链接: https://codeforces.com/contest/1265/problem/C 题意: So the Beautiful Regional Contest (BeRC) has c ...
- Codeforces Round #604 (Div. 2) B. Beautiful Numbers
链接: https://codeforces.com/contest/1265/problem/B 题意: You are given a permutation p=[p1,p2,-,pn] of ...
- Codeforces Round #604 (Div. 2) A. Beautiful String
链接: https://codeforces.com/contest/1265/problem/A 题意: A string is called beautiful if no two consecu ...
- Codeforces Round #604 (Div. 2) E. Beautiful Mirrors 题解 组合数学
题目链接:https://codeforces.com/contest/1265/problem/E 题目大意: 有 \(n\) 个步骤,第 \(i\) 个步骤成功的概率是 \(P_i\) ,每一步只 ...
- Codeforces Round #604 (Div. 2) 部分题解
链接:http://codeforces.com/contest/1265 A. Beautiful String A string is called beautiful if no two con ...
- Codeforces Round #604 (Div. 2) A. Beautiful String(贪心)
题目链接:https://codeforces.com/contest/1265/problem/A 题意 给出一个由 a, b, c, ? 组成的字符串,将 ? 替换为 a, b, c 中的一个字母 ...
随机推荐
- 【C/C++】指针
指针定义 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,必须在使用指针存储其他变量地址之前,对其进行声明.指针变量声明的一般形式为: type *var-na ...
- fork,vfork
转自 http://blog.csdn.net/todd911/article/details/14062103 1.fork函数 一个现有的进程可以调用fork函数创建一个新的子进程. #inclu ...
- 第09组 Alpha冲刺(4/6)
队名:观光队 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 完成服务器连接数据库部分代码 展示GitHub当日代码/文档签入记录 接下来的计划 服务器网络请求,vu ...
- shell 换行与不换行
test.sh: echo -e "hello w\norld!"echo -e "hello w\c"echo "orld!" 输出 bo ...
- pm2 启动模式 fork 和 cluster 的区别
fork模式,单实例多进程,常用于多语言混编,比如php.python等,不支持端口复用,需要自己做应用的端口分配和负载均衡的子进程业务代码. 缺点就是单服务器实例容易由于异常会导致服务器实例崩溃. ...
- GuavaCache简介(一)是轻量级的框架 少量数据,并且 过期时间相同 可以用 GuavaCache
还有一篇文章是讲解redis 如何删除过期数据的,参考:Redis的内存回收策略和内存上限(阿里) 划重点:在GuavaCache中,并不存在任何线程!它实现机制是在写操作时顺带做少量的维护工作(如清 ...
- 解析prototxt文件的python库 prototxt-parser(使用parsy自定义文件格式解析)
解析prototxt文件的python库 prototxt-parser https://github.com/yogin16/prototxt_parser https://test.pypi.or ...
- python windows下安装pip及rarfile
python之所以被广泛使用,倒不见得是本身语法简单,而是而nodejs/javascript一样把三方库的依赖管理简化了,而不用和java一样非得通过maven管理,而且还得打包后在classpat ...
- <c:forEach>, <c:forTokens> 标签
这些标签封装了Java中的for,while,do-while循环. 相比而言,<c:forEach>标签是更加通用的标签,因为它迭代一个集合中的对象. <c:forTokens&g ...
- base64加密后无法解密
记录一个问题: 使用java,或者命令行 base64 命令加密图片文件成加密数据后无法还原成图片 深入:使用java base64工具(sun base64或bouncycastle)加密的数据替换 ...