CodeForces - 893 Educational Codeforces Round 33
1 A Chess For Three CodeForces - 893A
1.1 题目大意
A, B, C三个小伙伴玩象棋
象棋规则如下:
第一局A与B对弈,C观战
每一盘游戏结束后,输的小伙伴将观战,刚刚观战的小伙伴将与胜者继续对弈
他们共下了n盘象棋,并且记录下来了每一盘的胜者
请问记录是否有错(观战的人胜利即为出错)
1.2 解题思路
用 spec[] 数组 记录一下当前小伙伴们的状态(true为观战,false为对弈)
依次判断是否出现观战者胜利即可
胜者状态不变,败者与观战者的状态取反
1.3 代码实现
1 |
|
2 B - Beautiful Divisors CodeForces - 893B
2.1 题目大意
在二进制表示中,前面有$x$个1后面有$x-1$个0的数我们之称为美丽数
题目提示:
More formally, the number is beautiful iff there exists some positive integer k such that the number is equal to $(2^k - 1) * (2^{k - 1})$.
给定一个n,问它的最大美丽数因子是多少
2.2 解题思路
根据题意我们知道,第一个美丽数是1,第二个是6
第$k$个美丽数满足$(2^k - 1) * (2^{k - 1})$
因此,小于n的美丽数不会超过$log_2 n$个
因此我们枚举美丽数判定即可
2.3 代码实现
1 |
|
3 C - Rumor CodeForces - 893C
3.1 题目大意
给定n个人
第$i$个人被贿赂需要$a_i$的代价
给定m个朋友关系
被贿赂的人会向他的朋友们免费传播谣言(当然,被贿赂的人已经算是被传播了谣言)
问这n个人都被传播谣言的最小代价是多少
3.2 解题思路
我们很容易知道
处于同一个朋友圈里的人,我们只需要贿赂这个朋友圈中所有人中代价最小的人
即可解决这个朋友圈
因此我们只需要并查集维护一下朋友圈以及朋友圈内的最小代价
然后枚举朋友圈,最小代价求和即是答案
3.3 代码实现
1 |
|
4 D - Credit Card CodeForces - 893D
4.1 题目大意
给定天数n,以及信用卡里的最大钱数d
每天晚上银行将会有一个操作$a_i$
如果$a_i == 0$ ,今天晚上将进行检查,如果信用卡里的钱数小于0,则信用卡将会被注销
如果$a_i > 0$,银行将在卡里充入$a_i$,否则将取走$a_i$
任何时刻卡里的钱数超过$d$元,信用卡将会被注销
你可以在每天早上去银行存钱(不可取钱)
问是否能够保证信用卡不被注销
可以的话,最少去银行存钱几次
4.2 解题思路
由于能够存钱,不能取钱
所以信用卡被注销,只有可能是因为信用卡里的钱超过了d元
因为在银行检查的当天,如果钱数小于零,在早上一定可以存钱使得其大于零
为了保证取得次数最少
我们在必须存钱时,一定是在保证在后续操作的钱数不超过d的情况下,存的越多越好
因此,我们只需要记录一下,在信用卡不被注销的情况下
当前可能的最大钱数是多少,当前可能的最小钱数是多少
当银行检查余额时
当前可能最小钱数如果小于零,则将置为0
当前可能最大钱数如果小于零则说明,我们必须进行一次存钱了,所以更新答案,将最大可能钱数置为 d
当银行进行存取钱操作时,更新最大最小钱数
如果最大钱数大于 d,则将其置回 d,保证满足题意
当当前可能的最小钱数大于d时,则信用卡一定会被注销
4.3 代码实现
1 |
|
5 E - Counting Arrays CodeForces - 893E
5.1 题目大意
q次询问
每次询问给定一个$x_i$和$y_i$
$y_i$个数的乘积为$x_i$的情况下,共用多少种排列情况
5.2 解题思路
我们将 $x$ 进行质因子分解
获得这样一种形式
这样的话,我们只需要考虑将每个特定的质因子分配给这$y$个数,一共有多少种情况
如果只能分配为正数时,总方案数将是这些质因子的方案数的乘积
加入某个质因子,它分解出来的个数是$cnt$个,将它们分配给$y$个数(允许分配零个)会有多少种情况呢
这样的话,相当于把$cnt$个球分配到$y$个桶里,允许空桶
使用隔板法的话,是不允许两个隔板之间的球的个数为零的
我们可以假设存在$cnt + y$个球,这样便可以使用隔板法后,每个桶里的球的个数 是 隔板间球的个数减一
即满足桶里球的个数可以为零,又满足使用隔板法的条件
这样的话,我们进行隔板法计算它的组合数将是
由于需要取模,所以需要预处理出来所有阶乘逆元
考虑负数的情况,由于给定的$x > 0$所以负数的个数将是偶数个
根据组合数的性质,所有奇数项的和等于所有偶数项的和,等于$tot = 2^{y - 1}$
因此最后的方案数需要乘上$tot$
由于直接暴力判定质因子,时间会超
所以我们考虑只枚举小于$sqrt(x)$的质因子
如果最后$x > 1$则说明x为一个素数
只需要乘上一个$C_y^1$也就是$y$即可
5.3 代码实现
1 |
|
6 F - Subtree Minimum Query CodeForces - 893F
6.1 题目大意
给定一棵n个节点以r为根的树,每个节点有一个权值 $a_i$
进行m次询问,每次询问以 x 为根节点, 距离不大于 k 的所有节点中,最小的权值是多少
询问强制在线(根据上次的答案解密下一次询问的 x 与 k)
6.2 解题思路
最多$10^5$个节点,$10^6$次询问,我们考虑使用线段树
由于有询问子树的需求,我们很容易想到获得这棵树的以r为根dfs序
在树的dfs序中,一棵树的子树部分,将会是连续的一个序列
因此我们便可以通过线段树来维护一些东西,搞一些事情
在重新审视题意,我们可以发现,假定dfs序列中以 x 为根的连续子序列是 $[lf, rt]$
要求距离 x 不超过 k, 因此在原树中,这些满足条件的节点深度在区间 $[d[x], d[x] + k]$ 中
因此我们所求的问题便转化为了,在二维坐标系中,在某个矩形区域内部点的最小权值
由于我们所求的最小值,没有可加减的性质,因此无法通过二维前缀和解决
这种情况下的解决办法有 kd树,树套树 等我还不会写的的神仙数据结构
因此我们继续审视题目,我们可以发现,在所给定的条件中
如果确定节点深度所在的区间,我们发现,它们的dfs序并没有什么特殊的性质
如果我们确定dfs序所在区间,我们可以发现,它们的深度一定大于$d[x]$(因为是以$x$为根节点的子树)
因此我们可以发现在深度 $[1, d[x])$ 中,没有任何节点处于其中
因此我们可以放心的将原问题转化为
在dfs序处于[lf, rt],并且相对于原数深度不大于$d[x] + k$的节点中,最小权值是多少
我们发现在深度这个维度
我们不再需要截断某一段去查询(因为可以直接查询小于等于$d[x] + k$)的所有节点
这样的话,我们便不需要在考虑最小值无法加减截断的事情
因此我们便只需要以dfs序建一棵线段树,以深度(从小到大)为时间线推进维护起来即可
即,我们需要建一棵,以dfs序为基,以节点深度为时间轴的主席树(留坑,以后补一篇博客)即可
6.3 代码实现
1341ms 48700kB
主席树真好写 才花了3个小时就写完了
1 |
|