B1. Character Swap (Easy Version)
B2. Character Swap (Hard Version)
题意:给你两个长度为n
的字符串s,t
,字符串只包含26个小写字母。你的操作是每次从两个字符串中分别挑一个字母出来交换,问能不能使得两个串相等。
- 第一问中你只能操作1次(且必须操作1次), n ≤ 10000 n\leq 10000 n≤10000
- 第二问中你最多可以操作 2 n 2n 2n 次, n ≤ 50 n\leq 50 n≤50
分析:对于第一问,只保留 s,t 中不同的字符。只有形如aa,bb
的长度为2的两个串可以在一次交换中完成任务。对于第二问,只要每个字母在两个串中出现的次数和都是偶数就有解;可以证明,最多2次操作就能将当前两个串中第一个不同的字母交换成相同的,总交换次数不超过2n。
题意:在一个1*n
的矩形中,如果两个格子
i
,
j
i,j
i,j 满足
∣
i
−
j
∣
|i-j|
∣i−j∣ 是n大于1的约数,这两个格子就要染成相同颜色。问染完所有格子最多用多少种颜色。
分析:1. 如果n是素数,那么任意两个格子都可以不同色。2. 如果n不是素数且只有1个素因子p,那么最多用p种颜色。3. 如果n有多个素因子,所有格子都必须同色。
题意:n
个顶点的完全图中所有边权都为0,现将其中m
条边权重变为1,问最小生成树的权重,其中
n
,
m
≤
1
0
5
n,m\leq 10^5
n,m≤105
分析:等价于在完全图上删若干条边后求连通分量数。同样有dfs和并查集两种写法。基于dfs的实现见代码。
题意:有k
个盒子,每个盒子里有若干个数,要求从每个盒子中取出1个数(共k个),再重新分配到k个盒子里,问能不能经过1次这样的操作使得盒子里的数的总和相同。
k
≤
15
k\leq 15
k≤15,每个盒子里不超过5000个数,所有的数两两不等。
分析:首先排除所有数总和s不是k的倍数的情况。如果s是k的倍数,那么最后每个盒子里的总和就是avg=s/k。如果第i个盒子当前数字和是Si,移除其中某个数x,我们可以计算出需要补进的数为y=avg-Si+x。由于所有数字两两不同,我们可以用有向图描述x,y之间的关系:每个数是一个顶点,从x引一条有向边到y。注意,来自同一个盒子的两个数之间不能引边,但可以从自己引向自己。在这张图上,一个大小为c的环就代表了c个盒子之间的数字置换。问题转化为能否找到若干个环,这些环覆盖所有的盒子,且没有两个环覆盖同一个盒子。
在实现上,因为数字的唯一性,图上的每个点都只有一条出边,因此所有环都不相交。求出所有的环之后,我们根据环覆盖的盒子情况给环做mask编码。最终答案就是k位全为1的编码能不能由这些mask拼凑出来。这是一个数位动规的问题,在动规的过程中,我们需要求一个编码所有的子编码,核心代码是下面这个两重循环,复杂度为 O ( 3 n ) O(3^n) O(3n),更多细节见代码。
for (int i = 1; i < (1<<n); i++) {
for (int j = i; ; j = (j-1)&i) {
// do sth with i, j
if (j == 0) break;
}
}