do_while_true

一言(ヒトコト)

「比赛题解」Codeforces Round #697 (Div. 3) 简要题解

A

\(\mathcal{Translate}\)

给定一个 \(n\),询问 \(n\) 是否能被大于 \(1\) 的奇数整除,若可以输出 \(Yes\),否则输出 \(No\)

\(2\leq n\leq 10^{14}\)

\(\mathcal{Solution}\)

考虑对这个数进行质因数分解,由于除 \(2\) 以外所有质数都是奇数,所以如果不是分解后只有 \(2\),那么一定有一个大于 \(1\) 的奇数因子。

故判断这个数是不是 \(2\) 的次幂即可。

\(\mathcal{Code}\)

B

\(\mathcal{Translate}\)

给定一个 \(n\),判断其是否能被分解为 \(2020\times x+2021\times y\) 的形式,其中 \(x,y\) 都是非负整数。

\(n\leq 10^6\)

\(\mathcal{Solution}\)

先把 \(n\) 分成若干个 \(2020\),然后肯定会剩下分不成 \(2020\) 的剩下的数,再把这些平均给分出来的 \(2020\)。这样肯定最优。

一共分出来 \(n/2020\)\(2020\),还剩下 \(n\% 2020\) 需要分配。

判断能不能分完即为判断这两个数的大小。

\(\mathcal{Code}\)

C

\(\mathcal{Translate}\)

共有 \(a\) 个男生,\(b\) 个女生,其中有 \(k\) 组男女愿意组成一对。现在要从中挑选出两对男女(不能重复),求一共有多少种挑选方法。

\(a,b,k\leq 2\times 10^5\)

\(\mathcal{Solution}\)

首先先去重。枚举每一对作为第一对,然后就是剩下的 \((k-1)\) 组中有多少组不包含枚举到的那一组的男女。提前记录每个男生和每个女生匹配了多少组,即可快速求出这个答案。

最后把算出来的答案除以 \(2\) 即为答案(因为每种合法的匹配被两组男女分别计算了一次。)

\(\mathcal{Code}\)

D

\(\mathcal{Translate}\)

现在有 \(n\) 个物品,第 \(i\) 个重量为 \(a_i\),代价为 \(b_i\)

现在要挑选出若干个物品,使其重量和 \(\geq m\),并且代价最小,输出这个代价。

\(1\leq n\leq 2\times 10^5,1\leq m\leq 10^9\)

\(1\leq a_i\leq 10^9,1\leq b_i\leq 2\)

\(\mathcal{Solution}\)

注意到 \(b_i\) 只有 \(1,2\) 是突破点,考虑类似于折半搜索的思想,把 \(b_i=1,2\) 的分开来。

各自根据 \(a\) 从大到小排序,这样各选一个前缀肯定是更优的,枚举选 \(b_i=1\) 的个数,然后在 \(b_i=2\) 的里面二分一个最小的前缀满足他们的和 \(>m\) 即可。

所有可能取最小值即为答案。

\(\mathcal{Code}\)

E

\(\mathcal{Translate}\)

给定长度为 \(n\) 的序列 \(a\),选出 \(k\) 个数使得他们的和最大,求一共有多少种选择方案。对 \(10^9+7\) 取模。

\(1\leq k\leq n\leq 1000,1\leq a_i\leq n\)

\(\mathcal{Solution}\)

从大到小选肯定是更优的,那么可能变换的只有选到的最小的那个,也就是第 \(k\) 大的数,计第 \(k\) 大的数共有 \(cnt\) 个,前 \((k-1)\) 大的数共有 \(sum\) 个。

根据组合数学基本知识可得方案数为 \(C_{cnt}^{k-sum}\)

\(\mathcal{Code}\)

F

\(\mathcal{Translate}\)

给定两个\(n\times n\)\(01\)矩阵 \(A,B\),询问 \(A\) 是否能经过一系列变换变成 \(B\)。变换为选一行或一列各自变成其 \(xor 1\)

\(1\leq n\leq 1000\)

\(\mathcal{Solution}\)

把两个矩阵异或一下,那么问题转化为一个矩阵是否能经过一系列变换变成全 \(0\)。这个变换可以看成每一位各自取反。

考虑两个性质:

  1. 一行或一列最多会被取反一次。因为取反偶数次相当于不取反,取反奇数次相当于取反一次。

  2. 若一个位置为 \(0\),则其当前行和当前列是否取反是相同的,否则相反。这样才能消成 \(0\)

考虑性质 \(2\),使得每一行和每一列都能连接起一个关系来,那么随便选一行或者一列,确定它是否取反,就能确定整个矩阵是否取反。

两种情况搞下来各检查一遍看是否合法即可。把每一行和每一列都看成一个节点,连成图更好写一些。

\(\mathcal{Code}\)

G

\(\mathcal{Translate}\)

给定一个长度为 \(n\) 的序列 \(a\),询问它至少要删除几个数使得它成为一个好的序列。

定义一个好的序列:这个序列中的任意两个数是整除或被整除关系。

\(\mathcal{Solution}\)

首先排下序,不影响答案。考虑到一个成为一个好的序列的充分必要条件是这个序列的相邻两个满足 \(a_i | a_{i+1}\),正确性显然。

\(f_i\) 代表考虑前 \(i\) 个并且选 \(i\),要成为一个好的序列最少删多少数。

\(f_i = \min \{f_{pos_j} + i - pos_j - 1\}\),其中 其中 \(j\)\(i\) 的约数, \(pos_j\) 代表 \(j\) 最后出现的位置。

直接 \(dp\) 即可,时间复杂度 \(\mathcal{O}(n\sqrt{a})\)

\(\mathcal{Code}\)

posted @ 2021-01-30 09:25  do_while_true  阅读(90)  评论(0编辑  收藏  举报