AtCoder Beginner Contests 342~359
补题情况:AtCoder Problems
ABC342
D
题意
给出 \(n\) 个数 \(a_1,a_2,\dots a_n\),求有多少对 \((i,j)\) 满足以下条件:
- \(1\leq i<j\leq n\);
- \(a_ia_j\) 为完全平方数(0 也是完全平方数)。
分析
我的解法与官方题解基本相同。
先将 \(a_i\) 从小到大排序。考虑对于每个 \(a_i\),统计他对答案的贡献。
如果 \(a_i=0\),那么他和后面的所有数都能组成符合要求的数对,答案加上 \(n-i\)。
如果 \(a_i\not= 0\),考虑 \(a_i\) 要和哪些数相乘才会形成完全平方数。完全平方数有一个性质:所有质因数的次数均为偶数。
设 \(a_i=\prod\limits_{k=1}^{q}p_k^{c_k}\),那么要找到一个小于等于 \(a_i\) 的 \(a_j=\prod\limits_{k=1}^{q}p_k^{d_k}\)(其中 \(p_k\) 均为质数,\(c_k,d_k\) 为自然数),使得 \(c_1+d_1,c_2+d_2,\dots,c_q+d_q\) 均为偶数。则 \(c_i\) 与它对应的 \(d_i\) 奇偶性相同。
那么就先把 \(a_i,a_j\) 分别除以 \(\prod\limits_{k=1}^{q}p_k^{2\left\lfloor\frac{c_k}{2}\right\rfloor}\) 和 \(\prod\limits_{k=1}^{q}p_k^{2\left\lfloor\frac{d_k}{2}\right\rfloor}\),显然得到的数中所有质因子的指数都为 1。如果得到的这两个数相等,则 \(a_ia_j\) 的所有质因数的指数都为偶数。
具体到代码实现上,预处理出 \(1\) 到 \(2\times 10^5\) 的完全平方数,对于每个 \(a_i\) 把它能被整除的完全平方数都除掉,统计前面有多少数经过处理之后和 \(a_i\) 剩下的数相等。
时间复杂度 \(O(n\sqrt{A_i})\)。
E
题意
有 \(n\) 个车站,编号为 \(1\) 到 \(n\)。给出 \(m\) 条火车的信息 \((l_i,d_i,k_i,c_i,A_i,B_i)\), 表示有 1 列火车在 \(l_i+\lambda d_i(\lambda\in \N,\lambda\leq k_i-1)\) 时刻从 \(A_i\) 站开出,在 \(l_i+\lambda d_i+c_i\) 时刻到达 \(B_i\) 站。
定义 \(f(S)\) 为从车站 \(S\) 到车站 \(N\) 的最晚时间(可以换乘)。如果无法到达,\(f(S)=-\infty\)。求 \(f(1),f(2),\dots,f(n-1)\)。
分析
Dijsktra 倒着推。
F
题意
你和一个 dealer 玩游戏。使用一个 \(D\) 面的骰子,每面的数字分别为 \(1\) 到 \(D\),每面出现的概率相等。
有两个初值为 0 的变量 \(x,y\)。你可以掷任意次骰子,每次将结果加到 \(x\) 上。
给定一个 \(L\),接下来,只要 \(y<L\),dealer 就会掷骰子,每次将结果加到 \(y\) 上。
给定一个 \(N\),如果游戏结束后,\(x>N\),你输了。否则,如果 \(y>N\) 或 \(x>y\) 你赢了。如果这两者都不满足,你输了。
求你获胜的最大概率。
分析
\(p_i,q_i,r_i\) 分别表示表示 \(y=i\) 的概率,结束时 \(x=i\) 的负率,\(x=i\) 状态下的胜率。
状态转移方程:
这样求 \(p_i\) 的时间复杂度是 \(O(ld)\) 的,会 TLE。所以再开一个数组 \(f_i\) 辅助求解 \(p_i\),把时间复杂度降到 \(O(l+d)\)。其他细节见代码注释。
G
题意
给定一个长度为 \(N\) 的数列 \(A=(A_1,A_2,\dots,A_N)\),有 \(Q\) 次操作,每次操作为以下三种之一:
- 给定一个三元组 \((l,r,x)\),把每个 \(A_i(l\leq i\leq r)\) 修改为 \(\max(A_i,x)\)。
- 给定一个整数 \(i\),把第 \(i\) 个操作取消。保证这个操作为操作 1,且之前没有被取消过。
- 给定一个整数 \(i\),求当前 \(A_i\) 的值。
分析
看到题目很容易想到线段树。
那个最速正解的代码实在看不懂
这里着重讲解怎么通过题目想出来的这个思路。
如果没有操作 2,那么这题和 P4560 [IOI2014] Wall 砖墙 是一样的。
有了操作 2,既然要访问之前的操作,那肯定要把之前的操作 1 都存起来。
对于一个数 \(A_i\),如果它经过了 \(A_i=\max(A_i,x_1),A_i=\max(A_i,x_2),\dots,A_i=\max(A_i,x_q)\) 这一系列操作,它的最终值为 \(\max(A_i,\underset{1\leq k\leq q}{\max}\{x_k\})\)。
如果要撤销之前的一个操作,那么就要考虑这个操作撤销了,对当前的 \(A_i\) 是否有影响。
设撤销的操作为 \((l,r,x)\),如果 \(A_i\) 不在 \([l,r]\) 这个区间内,那肯定没有影响。如果在 \([l,r]\) 这个区间内,把 \(x\) 与 \(\underset{1\leq k\leq q}{\max}\{x_k\}\) 作比较,如果 \(x<\underset{1\leq k\leq q}{\max}\{x_k\}\) ,也肯定没有影响。但如果 \(x=\underset{1\leq k\leq q}{\max}\{x_k\}\),就要分类讨论。
- 如果 \(\{x_k\}\) 中只有一个与 \(x\) 相等,那么当前的 \(A_i\) 就要修改为把 \(x\) 从 \(\{x_k\}\) 中删除后 \(\{x_k\}\) 剩下的最大值。
- 如果 \(\{x_k\}\) 中有多个元素与 \(x\) 相等,那么此撤销操作对 \(A_i\) 没有影响。
用 multiset 来维护 \(\{x_k\}\)。
在线段树原有修改、查询操作的基础上,再加一个撤销操作。
赛时有想到这个思路,结果时间全花 D 题上了。
ABC343
E
题意
定义 \(C(a,b,c)\) 为长、宽、高分别为 \([a,a+7],[b,b+7],[c,c+7]\) 的正方体。
求九个整数 \(a_1,b_1,c_1,a_2,b_2,c_2,a_3,b_3,c_3\) 满足以下条件:
- \(|a_1|,|b_1|,|c_1|,|a_2|,|b_2|,|c_2|,|a_3|,|b_3|,|c_3|\leq 100\)。
- \(C_i=C(a_i,b_i,c_i)(i=1,2,3)\)。
- 只被 \(C_1,C_2,C_3\) 中一个占领的体积为 \(V_1\)。
- 正好被 \(C_1,C_2,C_3\) 中两个占领的体积为 \(V_2\)。
- \(C_1,C_2,C_3\) 共同的重叠部分的体积为 \(V_3\)。
分析
先把 \(a_1,b_1,c_1\) 都定为 \(0\),枚举第二个和第三个正方形的坐标,容斥算出要求的三个值,check 即可。然后因为正方体的距离离太远是没有意义的,所以可以缩小枚举范围。把 \(a_2,b_2,c_2\) 在 \(0\) 到 \(7\) 之间枚举,把 \(a_3,b_3,c_3\) 在 \(-7\) 到 \(14\) 之间枚举。
一开始没过,发现自己枚举范围小了,结果后面又发现容斥算错了。
F
题意
给定一个长度为 \(N\) 的数列 \(A=(A_1,A_2,\dots,A_N)\),有 \(Q\) 次操作,每次操作为以下 2 种之一:
- 给定 \(x,y\),把 \(A_x\) 修改为 \(y\)。
- 给定 \(l,r\),询问 \(A_l\) 到 \(A_r\) 中严格次大值出现的次数。
分析
线段树板题。
每个节点存储四个值 \(mx,mm,cmx,cmm\),分别表示区间最大值、次大值、最大值出现的次数、次大值出现的次数。
G
题意
给定 \(n\) 个字符串 \(S_1,S_2,\dots,S_n\),求最短的字符串 \(T\) 长度,满足 \(S_1,S_2,\dots,S_n\) 都是 \(T\) 的子串。
\(n\leq 20\)。
分析
弱化版 CF25E。预处理出字符串两两之间的重叠长度,然后状压 DP。
ABC344
E
题意
给定一个长度为 \(N\) 的数列 \(A=(A_1,A_2,\dots,A_N)\),有 \(Q\) 次操作,每次操作为以下 2 种之一:
- 给定 \(x,y\),在 \(x\) 后面插入 \(y\)。
- 给定 \(x\),把 \(x\) 删除。
保证在任何时候,\(A\) 中的每个数都只出现一次。
输出最后的 \(A\) 数列。
分析
因为在任何时候,\(A\) 中的每个数都只出现一次,所以用两个 map 分别记录每个数的前驱和后继,按照更新链表的方法来更新就好了。
F
题意
有一个 \(n\times n\) 的棋盘,在每个格子 \((i,j)\) 上可以进行三种操作:
- 停留在这个格子上,并获得 \(P_{i,j}\) 元。
- 到达 \((i,j+1)\) 并支付 \(R_{i,j}\) 元。
- 到达 \((i+1,j)\) 并支付 \(D_{i,j}\) 元。
不能使钱数为负,也不能跑出棋盘外。
开始时你在 \((1,1)\) 的格子上,有 0 元,求最少需要多少次操作才能到达 \((n,n)\)。
\(n\leq 80\)。
分析
因为如果要移动的话,每一步要么往右走,要么往下走,所以移动的次数一定为 \(2(n-1)\)。关键就是要求出最小的操作 1 的次数。
先不考虑操作 1 ,假设就一直走下去,如果发现自己的钱数为负数,那么必须在之前的路径上找一些点停下来攒钱(即执行操作 1)。要使操作 1 的次数最小,就必须在之前的路径上找到 \(P\) 最大的格子停下来。容易发现,最优情况下停下来收集的 \(P\) 是递增的。
设 \(f_{i,j}\) 为走到 \((i,j)\) 时需要的操作 1 的最小次数,\(h_{u,v,i,j}\) 表示从 \((u,v)\) 到 \((i,j)\) 要花费的最小钱数,\(g_{i,j}\) 表示从 \((1,1)\) 到 \((i,j)\) 剩余的最多钱数。
\(h_{u,v,i,j}\) 递推即可。
最终答案为 \(f_{n,n}+2(n-1)\)。
ABC345
E
题意
有 \(N\) 个球排成一排。 左边的第 \(i\) 个球的颜色是 \(C_i\) ,数值是 \(V_i\) 。
高桥希望在不改变顺序的情况下,将这一行中的 \(K\) 个球移除,这样在排列剩余的球时,就不会有相邻的两个球颜色相同。此外,在此条件下,他希望最大化这一行中剩余球的总价值。
求高桥是否能移除 \(K\) 个球,使剩余一行中没有相邻的两个球颜色相同。如果可以,求剩余球的最大总值。
数据范围:
- \(1\leq K<N\leq 2\times 10^5\)
- \(K\leq 500\)
- \(1\leq C_i\leq N\)
- \(1\leq V_i\leq 10^9\)
分析
抄题解过了 4 个月后又来看这道题的我:???
很容易设计状态:\(f_{i,j,k}\) 表示在前 \(i\) 个球中移除 \(j\) 个球,最后一个球颜色为 \(k\) 的最大价值。并得出状态转移方程:
当 \(k=C_i\) 时:
当 \(k\not=C_i\) 时:
时间复杂度为 \(O(N^2K^2)\),空间复杂度为 \(O(N^2K)\)。
写出来是这个东西喵。虽然看起来很简单,但却让我调了很久
memset(f,-0x3f,sizeof f);
f[0][0][0]=0;
for(int i=1; i<=n; i++) {
for(int j=0; j<=min(i,k); j++) {
//cout<<"output:"<<i<<" "<<j<<endl;
for(int co=0; co<=n; co++) { //color
if(j==0) {
if(co==c[i]){
if(c[i-1]!=co)f[i][j][co]=f[i-1][j][c[i-1]]+v[i];
}
} else {
f[i][j][co]=f[i-1][j-1][co];
if(co==c[i]) {
for(int t=0; t<=n; t++) {
if(t!=co)f[i][j][co]=max(f[i][j][co],f[i-1][j][t]+v[i]);
}
}
}
//cout<<f[i][j][co]<<" ";
}
//cout<<endl;
}
}
考虑如何优化。
使用滚动数组把空间优化到 \(O(NK)\)。
那么很好,根据题解,为了优化掉颜色这一维,我们进行一个思路的转换:
\(f_{i,j}\) 表示保留第 \(i\) 个球,前面删除了 \(j\) 个球所获得的最大价值,这样就不用在转移时枚举前面球的颜色。得出状态转移方程:
注意此时答案为 \(\max\{f_{i,k-(n-i)}\}\)。
行,这回又要重写了
时间复杂度 \(O(N^2K)\),空间复杂度 \(O(NK)\),依然要使用滚动数组。
考虑怎么优化 \(\underset{t<i,C_t\not=C_i}{\max}\{f_{t,j-(i-t-1)}\}\) 这个东西。明显可以维护最大值和非严格次大值。
第一篇题解的代码实在是抽象
听说可以用贪心做,我赛时也这么想的,但策略错了。
F
题意
有一个简单的图,图中有 \(N\) 个顶点,编号为 \(1\) 至 \(N\) ,有 \(M\) 条边,编号为 \(1\) 至 \(M\) 。边 \(i\) 连接顶点 \(u_i\) 和 \(v_i\) 。
每个顶点上都有一盏灯。初始时,所有的灯都是熄灭的。
请至多执行 \(M\) 次以下操作,确定是否可以恰好打开 \(K\) 盏灯。
- 选择一条边。假设 \(u\) 和 \(v\) 是边的端点。切换 \(u\) 和 \(v\) 上的灯的状态。也就是说,如果灯亮着,则将其关闭,反之亦然。
如果可以恰好打开 \(K\) 盏灯,请打印实现该状态的操作序列。
分析
注意到亮灯的数目总为偶数。
对于每一个连通块,求出任意一棵生成树。发现一定能有一种方法使连通块中亮灯的个数为不大于连通块点数的最大偶数。从叶子节点往上推,对于每个节点,如果没有亮灯,就操作它与它父亲的连边。
ABC346
E
题意
有一个有 \(H\) 行和 \(W\) 列的网格。初始时,所有单元格都被涂上颜色 0。
按照顺序执行以下操作,\(i = 1,2,\dots ,M\)。
如果 \(T_i = 1\),则将第 \(A_i\) 行的所有单元格重新涂上颜色 \(X_i\) 。
如果 \(T_i = 2\),则将第 \(A_i\) 列的所有单元格重新涂上颜色 \(X_i\)。
完成所有操作后,对于网格上存在的每种颜色 \(i\),找到涂有颜色 \(i\) 的单元格的数量。
分析
一个方格 \((i,j)\) 的最终颜色,取决于对第 \(i\) 行的最后的操作 和 第 \(j\) 列的最后的操作中,较晚的那一个操作所涂的颜色。
可以先把每个操作保存下来,然后倒序操作。如果某一行已经被涂过色了,那么后面对这一行的操作都是无用的。根据这个性质,在进行某一操作时,将答案加上被操作的这一行中没有被覆盖的格子的个数。颜色为 0 的格子数量即为所有没有被覆盖的格子数量。
F
题意
对于一个字符串 \(X\) 和一个非负整数 \(k\),定义 \(f(X, k)\) 表示将 \(X\) 重复 \(k\) 次得到的字符串,\(g(X, k)\) 表示将 \(X\) 的每个字符重复 \(k\) 次得到的字符串。例如当 \(X = \texttt{abc}\) 时,\(f(X, 2) = \texttt{abcabc}, g(X, 3) = \texttt{aaabbbccc}\)。特别的,当 \(k = 0\) 时,\(f(X, k), g(X, k)\) 为空串。
给定两个字符串 \(S, T\) 和一个正整数 \(n\)。求最大的非负整数 \(k\) 满足 \(g(T, k)\) 是 \(f(S, n)\) 的子序列。
\(1 \le n \le 10^{12}\),\(1 \le |S|, |T| \le 10^5\)。
分析
懒得写题解了。去看看这篇。
需要重做。
G
题意
给定一个整数序列 \(A=(A_1,A_2,\dots,A_N)\)。
找出满足以下条件的整数对 \((L,R)\) 的数量:
- \(1\leq L\leq R \leq N\)。
- 在 \(A\) 的子序列 \(A_L,A_{L+1},\dots,A_R\) 中,有一个数恰好出现一次。
更确切地说,存在一个整数 \(x\),恰好有一个整数 \(i\) 满足 \(A_i=x\) 且 \(L\leq i\leq R\)。
分析
要枚举区间肯定是不行的,我们可以试试先枚举区间中的唯一整数。
对于每个 \(A_i\),如果它在 \(A_L,A_{L+1},\dots,A_R\) 中只出现一次,那么 \(A_L,A_{L+1},\dots,A_{i-1}\) 与 \(A_{i+1},A_{i+2},\dots,A_R\) 都不等于 \(A_i\)。设 \(l_i\) 为满足此条件的最小 \(L\), \(r_i\) 为满足此条件的最大 \(R\),则由乘法原理可得 \(A_i\) 对答案的贡献为 \((i-l_i+1)\times(r_i-i+1)\)。
\(l_i\) 与 \(r_i\) 的求法:
for(int i=1; i<=n; i++) {
l[i]=mp[a[i]]+1;
mp[a[i]]=i;
}
mp.clear();
for(int i=n; i>=1; i--) {
if(mp[a[i]])r[i]=mp[a[i]]-1;
else r[i]=n;
mp[a[i]]=i;
}
但这样很明显会重复统计,因为一个区间中可能有多个数只出现了一次。如何去重?
发现求答案就是求 \(N\) 个左下角为 \((l_i,i)\),右上角为 \((i,r_i)\) 的矩形的面积并。用扫描线做就好了。
ABC347
D
题意
给定非负整数 \(a,b, c\)。确定是否存在一对非负整数 \((x, y)\) 满足以下五个条件之一。如果存在这样的一对整数,打印其中任意一对。
分析
构造题。跟洛谷月赛第一题那种构造题差不多难度。
不知道我思路错哪了,一直有两三个点过不去。破防。
E
题意
有一个整数序列 \(A=(A_1,A_2,\dots,A_N)\) 长度为 \(N\),所有元素初始设置为 0。同时,有一个初始为空的集合 \(S\)。
按顺序执行以下 \(Q\) 个查询。在处理完所有的 \(Q\) 个查询后,请输出序列 \(A\) 中每个元素的值。第 \(i\) 个查询的格式如下:
给定一个整数 \(x_i\)。如果整数 \(x_i\) 在集合 \(S\) 中,从集合 \(S\) 中移除 \(x_i\)。否则,将 \(x_i\) 插入到集合 \(S\) 中。然后,对于每个 \(j=1,2,\dots,N\),如果 \(j\in S\),则将 \(|S|\) 加到 \(A_j\) 中。
\(|S|\) 表示集合 \(S\) 中的元素数量。
分析
upd:其实我讲的太复杂了。简而言之就是对于每个数字,求出它对答案的贡献。这个过程使用前缀和。
先来分析下样例。以样例 2 为例。
4 6
1 2 3 2 4 2
在 \(i=1,2,\dots Q\) 时,每个数是否出现在集合里,以及集合的大小:
| \(i\) | 1 | 2 | 3 | 4 | \(size\) |
|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 0 | 1 |
| 2 | 1 | 1 | 0 | 0 | 2 |
| 3 | 1 | 1 | 1 | 0 | 3 |
| 4 | 1 | 0 | 1 | 0 | 2 |
| 5 | 1 | 0 | 1 | 1 | 3 |
| 6 | 1 | 1 | 1 | 1 | 4 |
\(A_1=1+2+3+2+3+4=15\)
\(A_2=2+3+4=9\)
\(A_3=3+2+3+4=12\)
\(A_4=3+4=7\)
推广到一般情况:
\(vis_{i,j}\) 表示第 \(i\) 个操作后,\(j\) 是否在集合里,\(siz_{i}\) 表示第 \(i\) 个操作后集合的大小。
考虑到 \(vis_{i,j}\) 在 \(j\) 相邻的两次出现之间的值都是相同的,所以可以边遍历操作,边记录 \(x_i\) 上一次出现的位置 \(b_{x_i}\),如果 \(b_{x_i}\leq u<i\) 时,\(vis_{u,x_i}\) 的值都为 1,那么可以把 \(A_{x_i}\) 加上 \(\sum\limits_{k=b_{x_i}}^{i-1}siz_k\)。预处理出 \(siz\) 的前缀和。其他细节见代码。
F
题意
在一个 \(N\times N\) 的矩阵中找出三个不相交的 \(K\times K\) 的矩阵,求这三个矩阵的元素和的最大值。
分析
第一次见这种题,还真做不出来。
双倍经验 P3625。
ABC348
D
题意
有一个\(H\) 行和 \(W\) 列的网格。 \((i, j)\) 表示位于从上往下第 \(i\) 行和从左往右第 \(j\) 列的单元格。每个单元格有字符 \(A_{i,j}\) :
.:空单元格。#:一个障碍物。S:空单元格和起点。T:空单元格和目标点。
高桥可以通过消耗 \(1\) 能量从当前单元格移动到上下左右的空单元格。如果能量为 \(0\) ,他就无法移动,也无法离开网格。
网格中有 \(N\) 种药。 第 \(i\) 种药位于空格 \((R_i, C_i)\) 处,可以用来把能量 变成 \(E_i\) 。注意,能量并不一定会增加。他可以在当前格子中使用药物。使用过的药物会消失。
高桥以 \(0\) 的能量从起点开始,并希望达到目标点。请判断这是否可行。
分析
显然走到一个格子,如果格子中有药,如果药设定的能量不大于当前能量,那么就不会去使用它,否则会去使用它。
BFS 时将标记有没有走过改为记录走到当前格子的最大剩余能量。如果走到的格子记录的能量小于当前能量就入队。
E
题意
给出一棵 \(n\) 个点的树,以及每个点的权值 \(C_i\)。
设 \(d(u,v)\) 表示树上 \(u,v\) 两点之间的距离,设 \(f(x)=\sum\limits_{i=1}^n C_i\times d(x,i)\),求 \(\min\limits_{1\le v\le N}f(v)\)。
\(1\le N\le 10^5,\space 1\le C_i\le 10^9\)
分析
第一次 DFS 处理出每个点的子树结点权值之和(包括自身的权值)\(siz_u\),以及 \(f(1)\) 的值。
第二次 DFS 用第一次 DFS 处理出的数据推出其他节点的 \(f(x)\) 值。怎么推呢?
设节点 \(v\) 的父亲为 \(u\)。如下图,树被分成了两个部分。设第 \(i\) 各部分点的权值之和和对 \(f(u)\) 的贡献分别为 \(s_i,c_i\)。

F
题意
给出 \(N\) 个长度为 \(M\) 的序列 \(A_{1...N}\)。
求有多少对 \((i,j)\) 满足 \(i<j\),并且两个序列有恰好奇数个位置上的数相同,即 \(\sum\limits_{k=1}^M [A_{i,k}=A_{j,k}]\) 为奇数。
\(1\le N,M\le 2000,\space 1\le A_{i,j}\le 999\)
分析
暴力 \(O(N^2M)\),卡常可过。
正解反正是我根本不可能想到的玩意。
前置知识:bitset 用法 (https://blog.csdn.net/qq_44918090/article/details/130118709)
考虑枚举 \(i\),对于每个 \(i\) 计算与 \(A_i\) 相似的 \(A_j\) 的个数。
发现枚举两个序列是不可优化的,考虑优化判断两个序列相似的过程。
如果两个序列相似,把两个序列对应异或,得到的异或序列中 \(0\) 的个数为奇数。
对于一个 \(i\),枚举 \(j\),并开一个 bitset,\(B_{i,k,j}\) 表示 \(A_{i,j}\) 的二进制第 \(k\) 位上的数(最低位为第 0 位)。然后对于每个 \(i\),\(A_j\) 与 \(A_i\) 相似的条件就变为:对于每个 \(k\),\(B_{i,k}\) 异或 \(B_{j,k}\) 的结果全部或起来,结果中 1 的个数为奇数。原理是两个数每一位异或结果都为 0,两个数异或起来才为 0。
时间复杂度 \(O(\frac{N^2M\log W}{\omega})\)。其中 \(W\) 为序列值域,\(\omega\) 为 bitset 常数。
ABC349
F
题意
给你一个长度为 \(N\) 的正整数序列 \(A=(A_1,A_2,\dots,A_N)\) 和一个正整数 \(M\) 。求以 \(998244353\) 为模数,\(A\) 的非空且不一定连续的子序列的个数,使得子序列中元素的最小公倍数(LCM)为 \(M\) 。如果两个子序列取自序列中的不同位置,即使它们作为序列重合,也会被区分开来。此外,序列中单个元素的 LCM 就是该元素本身。
- \(1 \leq N \leq 2 \times 10^5\)
- \(1 \leq M \leq 10^{16}\)
- \(1 \leq A_i \leq 10^{16}\)
分析
设 \(M\) 的唯一分解为 \(\prod\limits_{i=1}^{r}p_i^{k_i}\)。则序列中的每个数 \(A_i\) 都满足 \(A_i|M\),且对于每个 \(p_i^{k_i}\),这些数中至少有一个能被其整除。因为 \(2\times 3\times 5\times 7\times 11\times 13\times 17\times 19\times 23\times 29\times 31\times 37\times 41\times 43>10^{16}\),所以 \(M\) 至多有 13 个质因数。对于每一个 \(A_i\),可以用一个 13 位的二进制数表示其状态,第 \(i\) 位表示它能被 \(p_i^{k_i}\) 整除。这些状态可以 \(O(N\times 13)\) 处理出来。此时问题转化成:有 \(N\) 个 \(r\) 位二进制数,求在其中选若干个使它们或起来为 \(2^r-1\) 的方案数。现在有两种解决方法:
法一:状压 DP
设计 \(dp_i\) 表示选出的数或起来为 \(i\) 的方案数。
初始状态 \(dp_0=1\),状态转移方程为 \(dp_{i|j}\leftarrow dp_{j}\)。时间复杂度 \(O(2^{r}\times N)\)。考虑优化。由于状态最多只有 \(2^{13}-1\) 个,所以有很多 \(A_i\) 的状态是重复的,那么只要枚举每个状态,而不用枚举每个 \(A_i\)。设状态为 \(k\) 的数有 \(cnt_k\) 个,则在这些数中取至少一个的方案数为 \(2^{cnt_k}-1\)。状态转移方程化为 \(dp_{i|j}\leftarrow dp_{j}\times (2^{cnt_i}-1)\)。时间复杂度 \(O(2^{2r})\)。
法二:容斥 + bitset 优化
【算法竞赛学习笔记】Bitset详解和应用_bitset优化-CSDN博客
正难则反。考虑用总方案数减去或起来的结果中有 0 的个数。枚举这些 0 的位置。根据容斥原理,要减去 0 的个数为奇数的方案数,加上个数为偶数的方案数。这个过程用 bitset 优化。
ABC350
E
题意
给定整数 \(N\) 。可以执行以下两种操作。
- 消耗 \(X\) 円将 \(N\) 变为 \(\lfloor \frac{N}{A}\rfloor\) 。
- 消耗 \(Y\) 円,在整数区间 \([1,6]\) 内等概率选取一个整数 \(B\) ,将 \(N\) 变为 \(\lfloor \frac{N}{B}\rfloor\) 。
求在最优策略下将 \(N\) 变为 \(0\) 需要消耗的最小円数。
- $ 1\ \leq\ N\ \leq\ 10^{18} $
- $ 2\ \leq\ A\ \leq\ 6 $
- $ 1\ \leq\ X,Y\ \leq\ 10^9 $
分析
自己写个程序搜一下发现只有 7254 种状态。这启发我们可以用 DP 或记搜来做。令 \(f_i\) 表示 \(i\) 变成 \(0\) 需要的最小円数的期望。
\(f_i=\min(f_{i/A}+X,\dfrac{1}{6}(f_{i}+f_{i/2}+f_{i/3}+f_{i/4}+f_{i/5}+f_{i/6})+Y)\)
左边和右边都出现了 \(f_i\),消去其中一个。
\(f_i=\min(f_{i/A}+X,\dfrac{1}{5}(f_{i/2}+f_{i/3}+f_{i/4}+f_{i/5}+f_{i/6})+\dfrac{6}{5}Y)\)
然后记搜就可以了。记得开 double。
F
题意
给定一个字符串 \(S=S_1S_2S_3\dots S_{|S|}\) ,由大写和小写英文字母、( 和 ) 组成。保证字符串 \(S\) 中的括号是正确匹配的。
重复以下操作,直到无法再执行操作为止:
- 首先,选择一对满足以下条件的整数对 \((l,r)\):
- \(l<r\)
- \(S_l=\)
( - \(S_r=\)
) - \(S_{l+1},S_{l+2},\dots,S_{r-1}\) 都是大写或小写英文字母。
- 令 \(T=\overline{S_{r-1}S_{r-2}\dots S_{l+1}}\)。
- 这里,\(\overline{x}\) 表示把 \(x\) 的大小写反转后得到的字符。
- 然后,删除字符串 \(S\) 中的第 \(l\) 到第 \(r\) 个字符,并在删除发生的位置插入字符串 \(T\)。
可以证明,可以使用上述操作将字符串中的所有 ( 和 ) 删除,并且最终字符串与执行操作的方式和顺序无关。
确定最终字符串。
分析
D 做完还剩一个小时,本来能场切这题的。其实是想到了正确思路但不会写。赛后自己写出来了。
感觉这题代码难度有一点点大。
直接模拟会 T,容易发现连续的英文字母是否倒序输出 以及 是否转换大小写 与它们所在的括号层数有关。以样例 2 为例:
//最外层括号外的字母为 1 层
Input:
cmk((ABC)n(X(y)ZW))aya
1112333332334443332111
Output:
cmkXYZWNABCaya
这个层数用栈来处理。同时处理出每个括号匹配的括号的位置。
层数为奇数的要正序输出,不用转换大小写;层数为偶数的要倒序输出,转换大小写。按这个原则来写就行了。
从第 1 个字符开始,如果是 (:
- 如果层数为偶,跳到与该括号配对的
)的前一个字符。 - 否则跳到下一个字符。
如果是 ):
- 如果层数为偶,跳到前一个字符。
- 否则跳到与该括号配对的
(的下一个字符。
如果一对括号中的内容都输出完了:
- 如果层数为偶,跳到这一对中
)的下一个字符。(因为这一对括号外面的那一层是正序输出) - 反之跳到
(的前一个字符。
ABC351
D
题意
有一个用字符类型表示的 \(H\) 行 \(W\) 列的地图 \(S\),如果 \(S_{i,j}\) 是字符 . 则代表这一格是空地,如果是 # 则代表这一格上有一个磁铁。
现有一个小人从一个格子上出发,每次可以到达与之相邻(上、下、左、右)的四个格子,但如果有一个磁铁与之相邻(上下左右的四个格子中至少有一个磁铁)他就不能动了。求小人从某一格出发,经过任意多次运动,可以到达的格子的最大数量。
分析
先把所有 # 的格子和他周围的 4 个格子打上标记。然后把没打标记的格子与它周围没打标记的格子连边。然后从一个能走的格子开始 DFS,每次 DFS 用一种颜色做标记(防止走回头路),并统计答案。
E
题意
位置 \((x, y)\) 可以一步跳到 \((x+1, y+1)\) 、 \((x+1, y-1)\) 、 \((x-1, y+1)\) 或 \((x-1, y-1)\) 。
\(\text{dist}(A, B)\) 定义为从点 \(A\) 跳到点 \(B\) 所需的最少跳跃次数。
如果经过任意次数的跳跃都无法从点 \(A\) 到达点 \(B\) ,则设为 \(\text{dist}(A, B) = 0\) 。
给定 \(N\) 个二维点 \(P_1 , P_2, P_3,\dots,P_N\)
计算
分析
切比雪夫距离转曼哈顿距离板子题。
ABC352
E
题意
给定一个带权无向图 \(G\),有 \(N\) 个顶点,编号为 \(1\) 到 \(N\)。初始时,\(G\) 没有边。
你将执行 \(M\) 个操作,向 \(G\) 中添加边。第 \(i\) 个操作如下:
给定一个顶点的子集 \(S_i=\{A_{i,1},A_{i,2},…,A_{i,k_i}\}\),其中 \(k_i\) 个顶点。对于每对在 \(S_i\) 中的顶点 \(u,v\)(\(u,v\in S_i\) 且 \(u<v\)),添加一条权重为 \(C_i\) 的边连接顶点 \(u\) 和 \(v\)。
执行完所有 \(M\) 个操作后,判断 \(G\) 是否连通。如果是连通的,找到 \(G\) 的最小生成树的所有边的总权重。
分析
赛时:这不就最小生成树板子吗。(然而我想多了,我用加入点集的点数来计算,结果炸了)
赛后:这不是直接按 Kruskal 的写法来写就行了吗???我当时在干什么???
总之破防了,在比赛结束前 10 min 我都认为自己能写出来。
至于我赛时的做法为什么是错的(甚至还能过样例),有一组 Hack 数据:
4 3
2 1
1 2
2 2
3 4
2 3
2 3
正确答案是 6,然而赛时代码输出 7。
ABC353
是 ABC 最爱的 Sigma Problems,我们有救了。

C
题意
对于正整数 \(x\) 和 \(y\) ,定义 \(f(x, y)\) 为 \((x + y)\) 除以 \(10^8\) 的余数。
给你一个长度为 \(N\) 的正整数序列 \(A = (A_1, \ldots, A_N)\) 。求下面表达式的值:
\(\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^N f(A_i,A_j)\) 。
分析
C 最有难度的一集。
D
题意
对于正整数 \(x\) 和 \(y\) ,定义 \(f(x, y)\) 如下:
- 将 \(x\) 和 \(y\) 的十进制表示解释为字符串,并按此顺序连接,得到字符串 \(z\) 。将 \(f(x, y)\) 解释为十进制整数时,其值就是 \(z\) 的值。
例如, \(f(3, 14) = 314\) 和 \(f(100, 1) = 1001\) 。
给你一个长度为 \(N\) 的正整数序列 \(A = (A_1, \ldots, A_N)\) 。求以下表达式 modulo \(998244353\) 的值:
\(\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^N f(A_i,A_j)\) 。
分析
不要用 pow 函数!!!不要用 pow 函数!!!不要用 pow 函数!!!
ABC354
E
题意
分析
ABC355
D
题意
给你 \(N(2 \leq N \leq 5 \times 10^5)\) 个实数区间。第 \(i\) \((1 \leq i \leq N)\) 个区间是 \([l _ i, r _ i](0 \leq l_i < r_i \leq 10^9)\) 。求有多少对 \((i, j)(1 \leq i < j \leq N)\) 中,\(i\) 和 \(j\) 两个区间相交。
(洛谷翻译不清楚,这里的相交指的是只要有重叠部分就算相交,包括共有端点)
分析
按右端点从小到大排序,对于每一个区间,统计在它前面的区间有多少个与他重合。因为右端点排好序了,所以只要统计它前面的区间的右端点有多少个大于等于它的左端点。
ABC356
D
题意
给你 2 个整数 \(n\) 和 \(m\)(\(0\le n,m < 2^{60}\)),请你求出
其中,\(\operatorname{and}\) 表示按位与,\(\operatorname{popcount}(x)\) 表示 \(x\) 的二进制表示中 1 的个数。
分析
发现 AtCoder 的计数问题很喜欢采用“转化”的方法。
在这道题中,popcount 之和可以转化成在对应的数位上出现 1 的次数之和。根据按位和的性质,被统计到的数位都是在 \(m\) 的二进制中为 1 的数位。
令二进制数的最低位为第 0 位,观察可以发现,从 0 开始,第 \(i\) 位是先出现 \(2^i\) 个 0,再出现 \(2^i\) 个 1,这样一直循环下去。利用这个性质来统计答案。
如果第 \(i\) 位在 \(m\) 的二进制中为 1,那么在 0 到 \(n\) 将会出现 \((n+1)/2^{i+1}\) 个完整的循环节,对答案有 \((n+1)/2^{i+1}\times2^i\) 的贡献,余数若大于 \(2^i\),还要再加上余数减去 \(2^i\)。
E
题意
给定长度为 \(N\) 的序列 \(A = (A_1,…,A_N)\),求:
分析
法一
先考虑 \(A_i\geq A_j\) 的情况,正着和倒着分别算一遍。\(A_i=A_j\) 的情况不要算两次。
根号分治,\(A_j\leq 1000\) 的把答案存起来,要的时候再加上,\(A_j>1000\) 的枚举倍数。
时间复杂度 \(O(N\sqrt{A_{i}})\)。
当然也可以先把数组排序,只要算一遍。

浙公网安备 33010602011771号