暑期集训
7.5 进阶分治
P7482
序列分治。
首先考虑单个区间的最大独立集怎么算。这个显然可以 dp,\(f_i = \max(f_{i-2} + a_i, f_{i-1})\)。
分治的时候考虑跨过中点的怎么算。关键的结论是两边的最大独立集是可以合并的,只需让 \(mid\) 和 \(mid+1\) 不同时选就好了。于是维护 \(f_i\) 表示 \([i, mid]\) 的最大独立集,\(g_i\) 表示 \([i,mid)\) 的,\(h_i\) 表示 \((mid, i]\) 的,\(l_i\) 表示 \((mid+1,i]\) 的。分别 dp 维护。那么答案就是 \(\max(f_i + l_j, g_i + h_j)\)。
暴力枚举 \(i,j\) 的话复杂度实际上还是不对的。必须把括号拆掉,分讨情况:
- \(f_i + l_j \ge g_i + h_j\),即 \(f_i - g_i \ge h_j - l_j\)。此时贡献取前者,可以二分 \(j\)。
- \(f_i + l_j \le g_i + h_j\),即 \(f_i - g_i \le h_j - l_j\)。同理此时贡献取后者。
那么枚举 \(i\),二分 \(j\) 计算答案即可。毒瘤题目。
void solve(ll l, ll r) {
if (l == r) return R = add(R, A[l]), void();
ll mid = l + r >> 1;
solve(l, mid); solve(mid + 1, r);
for (ll i = max(0ll, l - 3); i <= r + 3; ++ i ) sh[i] = so[i] = f[i] = g[i] = o[i] = h[i] = 0;
for (ll i = mid; i >= l; -- i ) f[i] = max(f[i + 1], f[i + 2] + A[i]);
for (ll i = mid - 1; i >= l; -- i ) g[i] = max(g[i + 1], g[i + 2] + A[i]);
for (ll i = mid + 1; i <= r; ++ i ) h[i] = max(h[i - 1], h[i - 2] + A[i]);
for (ll i = mid + 2; i <= r; ++ i ) o[i] = max(o[i - 1], o[i - 2] + A[i]);
L = 0;
for (ll i = mid + 1; i <= r; ++ i )
p[++ L] = {h[i], o[i]};
sort(p + 1, p + L + 1, pp);
for (ll i = 1; i <= L; ++ i )
sh[i] = add(sh[i - 1], p[i].h);
for (ll i = 1; i <= L; ++ i )
so[i] = add(so[i - 1], p[i].o);
assert((r - mid) == L);
sh[L + 1] = so[L + 1] = 0;
// cout << l << ' ' << r << ' ' << mid << ' ' << L << '\n';
for (ll i = l; i <= mid; ++ i ) {
ll xval = f[i] - g[i];
ll p = find(xval);
if (p == -1) p = L + 1;
R = add(R, (f[i] % mod) * (p - 1) % mod);
R = add(R, so[p - 1]);
R = add(R, (g[i] % mod) * (L - p + 1) % mod);
R = add(R, sh[L] - sh[p - 1] + mod);
}
}
P4755
由于我们关心最大值,考虑按最大值分治。对于区间 \([l,r]\),找到区间最大值位置 \(x\),如果有多个取任意一个,这个用 st 表可以维护。那么区间分裂成 \([l,x)\) 和 \((x,r]\)。考虑以 \(a_x\) 为 \(max\) 时候的贡献。在左侧枚举 \(i\),只需寻找右侧有多少 \(j\) 满足 \(a_j \le \frac{a_k}{a_i}\) 即可。然而排序后二分的复杂度是错的。这是因为不同于序列二分,可以构造最大值位置,类似快速排序卡成 \(O(n^2)\)。因此使用启发式合并的思想,枚举长度小的那一边,由于我们只需要求特定区间内 \(\le\) 某个值 \(x\) 的个数,可以离线下来用树状数组做。时间复杂度 \(O(n\log^2 n)\),不会证。
CF1175F
法一
考虑子区间 \([l,r]\) 是排列,那么有:
- 最大值是区间长度。
- 区间无重复元素。记 \(p_i\) 表示上一个与 \(i\) 相同的元素。满足 \(\forall i \in [l,r] p_i < l\)。
依旧是按最大值分治。这样就确定了区间长度。然后是套路地,枚举较短的一段,枚举作为左 / 右端点,那么确定了另一端的长度,使用数据结构维护区间内 \(p\) 的最小值即可。做完了。
法二
考虑 T647135 这个题。题意是求序列中排列的最大长度。这个题里我们从 \(1\) 开始往右暴力扩展,记录最大值另一端的判断使用 xor-hashing。然后再倒着做一遍,这样在线性时间解决了问题。
7.6 计数
P6075
神秘结论题。由于各个元素之间互不影响,考虑对于集合中每个元素单独做。那么对于每个元素 \(x\),这个三角形里每个位置的子集就只有包含 \(x\) 和不包含 \(x\) 两个状态,记为 \(1/0\)。那么对于每个 \(1\),要求其左上方部分都为 \(1\),相当于在三角形内部画一条分界线。把这个等腰直角三角形旋转到底在底下的状态,那么这条分界线就是从顶部走到底部任意一点的方案数,容易发现步数就是 \(k\),那么方案数就是 \(2^k\)。\(n\) 个元素方案数就是 \(2^{kn}\)。
P3223
容斥。不考虑老师是否相邻放进去就是 \(\binom{n+3}{m} \times (n+2)! \times m!\),考虑老师相邻就看做整体,\(\binom{n+2}{m} \times (n+1)! \times m! \times 2\),两者相减即为答案。
P6008
挺清新的题。首先对于每个联通块单独做。对于某个联通块,模拟水位上升的过程。对于单独一个空,方案数 \(f = 2\),可以填水可以不填。然后令当前的水位为 \(h\),现在枚举水位 \(h + 1\),那么就会有若干个块被合并到一个块内,方案数就是几个块方案数之积。最后注意得到新的块方案数要 \(+1\),因为得到的实际上是水位 \(h+1\) 及以下的方案数,水位 \(h\) 填满也是一种方案。
使用 dsu 维护即可。注意同一行可能合并到不同的块内。
UESTC1147
求最短路径方案是简单的。在跑最短路的时候计算就好。问题在于由于边权可能为 \(0\),可能有无限条最短路。这个怎么判呢?只需判断边权为 \(0\) 的边是否在某条最短路径上即可。我们正着反着跑两遍最短路,分别记为 \(f,g\)。那么记这条边为 \((u,v,0)\),判断 \(f_u+g_v\) 是否等于最短路径长度 \(f_n\) 即可。
CF439E
人话就是把 \(n\) 分成 \(f\) 个数之和,要求 \(f\) 个数的最大公约数为 \(1\)。多次询问。
考虑容斥。记 \(f(n,m)\) 表示 \(n\) 分成 \(m\) 个数之和的方案数。总的方案数是 \(\binom{n-1}{m-1}\),然后考虑不合法的方案数,枚举最大公约数为 \(d\),即 \(gcd(a_1,a_2,\cdots,a_m) = d\),记 \(a_x = d \times b_x\),那么 \(gcd(b_1,b_2,\cdots b_m) = 1\)
7.7 STL
P3644
首先把不用过桥的扔掉,把过桥的贡献预处理。
考虑 \(K = 1\),那么此时相当于找一个点到这 \(2n\) 个点距离最短。经典中位数,取第 \(n\) 个点即可。
\(K = 2\)。记两座桥坐标分别为 \(X_1,X_2\)。手玩一下可以发现 \(X_1\) 左侧的人一定走 \(X_1\),\(X_2\) 右侧的人一定走 \(X_2\)。中间的人只需判断家与工作地的中点与 \(X_1,X_2\) 中点的关系。
那么把每个人的家和工作地的中点 \(p\) 拿出来排序。枚举 \(X_1,X_2\) 中点,左右侧分别是 \(K = 1\) 的子问题。动态维护前后的中位数即可。接下来考虑距离怎么算。
7.9 dp
106554A
由于一包馍片只能扔一次,那么用两个序列 \(A,B\) 记录扔了一次 / 没扔的馍片。注意到我们只关心序列末尾馍片的值,于是 dp 时只记录 \(A,B\) 末尾的值即可。还要记录 \(A\) 的头部来与 \(B\) 的末尾做一个贡献。
由于值域很小,可以开四维的数组进行 dp,\(f_{i,j,k,l}\) 表示处理前 \(i\) 个元素,扔了一次的序列 \(A\) 的头部尾部分别为 \(j,k\),没扔序列的尾部为 \(l\)。把 \(i\) 那维滚掉即可。时间复杂度 \(O(nV^3)\),其中 \(V = 5\)。注意通过特判 \(l = 0\) 或者 \(j=k=0\),此时序列为空,没有贡献。
CF2209E
爆了。记字符串为 \(s\)。
\(q\le100\) 显然是让我们 \(O(qn)\) 做的。每组询问直接把字符串摘出来,然后做 dp。\(f_i\) 表示前 \([1,i]\) 的 \(f\) 值,答案即为 \(\sum_{i=1}^{r-l+1} f_i\)。考虑 \(f_i\) 怎么求。
把转移方程刻画一下,\(f_i = \max(f_{j-1} + 1)\),其中 \([j,i]\) 为 \(s\) 的某个前缀。你发现能转移的 \(j\) 点满足 \(s_{j\sim i} = s_{1\sim i - j + 1}\),这实际上是位置 \(i\) 的一个 border。手玩可以发现为了让 \(f\) 更大,这个 border 肯定越短越好。那么记 \(g_i\) 表示位置 \(i\) 的最小 border,有 \(f_i = f_{i-g_i} + 1\)。
记 \(nxt_i\) 表示 \(s\) 的 next 数组。对于 \(g_i\) 的求法,有以下几种情况:
- \(nxt_i=0\),此时 \(g_i=i\)。即该串无 border。
- \(nxt_{nxt_i} = 0\),此时 \(g_i = nxt_i\)。即此时为最小 border。
- 否则,\(g_i = nxt_{nxt_i}\)。这是因为 border 的 border 还是 border。
那么做完了。时间复杂度 \(O(qn)\)。给了 4s 可以通过。
P10977
依旧刻画转移方程:\(f_i = \max(f_{j-1} + \max(A_j,A_{j+1}\cdots A_i))\)。其中 \(j\) 还要满足 \(A_{j\sim i}\) 的区间和 \(\le m\)。这个显然可以二分把 \(j\) 的范围定在 \([p, i]\)。
注意到这个跟 P6647 很像。不同在于 \(p\) 不是固定的。
7.15 模拟赛
P15861
不会这个题还有救吗。
考虑 \(m = n(n-1)/2\),此时显然直接放 \(n\) 个相同元素是对的。考虑微调,记相同元素为 \(p\)。找到最大的 \(n_0\) 使 \(n_0(n_0 - 1)/2 < m\),记 \(t = m - n_0(n_0 - 1)/2\),要有 \(t\) 的贡献,只需要在第 \(t\) 个 \(p\) 后插入一个 \(2p\) 就好了。那么做完了。注意特判 \(m=0\)。
7.16 模拟赛
P11829
诈骗题。赛时结论猜对了一半只有 \(88\)。
我们按子任务一步一步考虑:
子任务 1
\(m=n-1\),此时为一棵树。由于树本身就不存在环,因此随便怎么分都可以。
子任务 2
保证存在两个以上的栖息地互相无法抵达。即连通块数量 \(\ge 2\)。
思考什么情况会构成环,由于不同连通块之间肯定不会构成环,容易发现当且仅当三个团体都有点在同一连通块内,才有可能构成环。
由于连通块数量 \(\ge 2\),不让三个团体的某些点放在同一连通块即可。具体可以把一个团体放在一个连通块,另外两个团体放在另外一个不同的连通块,这是容易做的。
正解
现在只有 \(1\) 个连通块,原图是联通的。
不妨记三个团体分别为 \(A,B,C\)。
大胆猜测我们总是把 \(A,B,C\) 的点数划分成 \(1,1,n-2\),这是因为同一团体内点数更多是不优的,这样只会增加更多的边数,更可能形成环。
考虑随机化,每次随机两个不同的点 \(x,y\) 放入 \(A,B\),剩下的点放入 \(C\)。赛时的想法是如果 \(x,y\) 之间没有边就不会形成环,那么判断一下就好了。但是这样只有 \(88\),这是因为存在一个反例:

这个时候也会形成环,考虑避免这个情况。我们分讨 \(x,y\),记点 \(p\) 的邻居集合为 \(S(p)\):
- \(x,y\) 之间没有边,这个时候需要 \(|S(x) \cap S(y)| \le 1\),即 \(x,y\) 至多只有一个公共邻居。
- \(x,y\) 之间右边,这个时候需要 \(|S(x) \cup S(y)| = \emptyset\),即 \(x,y\) 没有公共邻居。
那么使用 set 维护 \(x,y\) 邻居的集合即可。由于边数较小随机化的次数不会太多。
P12401
7.17 模拟赛
CF425E
考虑 \(S\) 确定的情况怎么求 \(f(S)\)。贪心策略是把线段按右端点排序,每次选当前能选的右端点最小的线段。
然后由于我们关心这个右端点的位置,把它放进状态。\(f_{i,j}\) 表示选了 \(i\) 条线段,当前贪心到的右端点为 \(j\),考虑所有端点 \(\le j\) 的线段的方案数。枚举选的上一条线段 \(j\) 的右端点 \(p\) 进行转移。然后我们考虑线段 \([l, r]\):
- \(l,r \le p\),这个在 \(f_{i-1,p}\) 已经考虑了。
- \(l \le p\) 且 \(p < r \le j\)。这种线段肯定不会被选,可有可无,总方案数 \(2^{(j - p) \times p}\)。
- \(l > p\) 且 \(p < r < j\)。这些线段不能存在。
- \(l > p\) 且 \(r = j\)。这么多线段有一条足矣,总方案数 \(2^{j - p} - 1\)。
那么转移 \(f_{i,j} = \sum f_{i-1,p} \times (2^{j-p}-1) \times 2^{(j-p) \times p}\)。预处理 \(2\) 的幂次可以做到 \(O(n^3)\)。
7.20 训练赛(F)
L The Vault of Stars
很妙妙的容斥。
首先考虑没有限制的时候咋做。这相当于把 \(S\) 个球放进 \(n\) 个盒子里,盒子可以为空。简单计数即为 \(\binom{S + n - 1}{n - 1}\)。
现在考虑求解不满足条件的方案数,即 \(\exists i\) 使得 \(X_i > L_i\)。
考虑不满足的 \(X_i\) 的个数,先考虑至少存在 \(1\) 个 \(i\) 满足 \(X_i > L_i\),枚举这个 \(i\),剩下的可以任意给。此时我们令 \(X_i \leftarrow X_i - L_i - 1\),这样问题又转化为没有限制的情况,方案数 \(\binom{S' + n - 1}{n - 1}\),其中 \(S' = S - L_i - 1\)。
然后考虑至少存在 \(2\) 个 \(i\) 满足 \(X_i > L_i\),枚举这两个不满足的 \(i,j\),那么同理可得方案数 \(\binom{S'' + n - 1}{n - 1}\),其中 \(S'' = S - L_i - 1 - L_j - 1\)。注意根据容斥,这个方案数要加上。
那么显然可以直接写个爆搜去求,但这样有些麻烦。考虑把上面的情况写成一般形式,记当前不满足条件的物品集合为 \(T\),那么贡献就是 \((-1)^{|T|} \times \binom{S' + n - 1}{n - 1}\),其中 \(S' = S - \sum_{i\in T} (L_i+1)\)。利用二进制枚举 \(T\) 即可。时间复杂度 \(O(2^nn)\)。
注意这个组合数计算,由于 \(S\) 可能很大,根据组合数公式 \(\binom{n}{m} = \frac{n!}{m!(n-m)!}\),预处理 \(m!\) 的逆元,然后暴力求 \(n(n-1)\cdots (n-m+1)\) 即可。
7.21 训练赛(H)
爆了。
I Exercise
考虑贪心。考虑两个题 \(i,j\) 的先后顺序,推导得到当 \(b_it_j > b_jt_i\) 时,\(j\) 在 \(i\) 前面。也就是 \(\frac{b_i}{t_i}\) 更大的要放前面。于是按这个东西排序,做一遍 01 背包即可。时间复杂度 \(O(n\log n + nT)\)。
J ACM
神了。
先考虑两个部分的情况,分讨 \(h_1,h_2\):
- \(h_1 < h_2\),这类题目先手肯定不会去碰的,这样只会更劣。也就是说,这类题目双方都不会碰。
- \(h_1 \ge h_2\),这类题目可以跟单部分题目一起考虑。
那么我们把情况 2 的题和单部分题目放在一起考虑,用大根堆维护轮流去取。对于剩下情况 1 的题目,容易证明此时的先手必定会拿到所有的 \(h_1\),后手必定拿到所有的 \(h_2\)。那么做完了。时间复杂度 \(O(n\log n)\)。
L String Doubling
不会这个题,是不是该退役了。
考虑倒着推,思考怎么从当前的位置推导出这次操作前的位置:
- 当前为操作 \(1\)。如果加的这个字符正是我当前的位置,那么直接输出。否则位置不变。
- 当前为操作 \(2\)。位置不变。
- 当前为操作 \(3\)。如果当前位置在后半段,就变到前半段去。具体的,假设当前位置为 \(P\),当前串的长度为 \(L\),如果 \(P > \frac{L}{2}\),那么有 \(P \leftarrow P - \frac{L}{2}\)。否则不变。
那么先维护每次操作后串的长度,离线下来倒着推即可。时间复杂度 \(O(tq)\)。
7.22 edu 训练
D Two Digit Strings
无敌了。
考虑合并的过程,我们实际上把原数字串划分成了若干段,每一段进行合并。这样问题就变成把这两个数字串分别划分成 \(L\) 段,要求每一段数字和 \(\bmod 10\) 一一对应相等。求 \(L\) 的最大值。
止步于此了。对两个串分别做一遍前缀和,记得到的前缀和为 \(s,t\)。考察匹配的过程,你发现我们总是在匹配两个相同的 \(s_i,t_j\),很妙的东西是对 \(s,t\) 做一遍 LCS 就完了。
E Product of Closures
爆了。考察选手的注意力。
分类讨论。记 \(r\) 的最高位为 \(k\),即有 \(2^k \le r\),故 \(r\) 在二进制下共 \(k+1\) 位。
- 若 \(l,r\) 在二进制下位数相等。我们找到 \(l,r\) 从高到低第一个不相等位,前面的位显然要求 \(x,y\) 与 \(l,r\) 一致。在这一位,我们令 \(x\) 的这一位为 \(0\),\(y\) 的这一位为 \(1\),这样 \(x\) 后面的位全放 \(0\),\(y\) 后面在满足 \(\le r\) 的条件下随便放。这样的构造可以让最终序列对应的位置全是 \(0\),是最优的。
- 若 \(l,r\) 在二进制下位数相差 \(1\)。考虑 \(x,y\) 位数不同的情况,显然令 \(y = 2^k\),考虑 \(x\) 怎么取,手玩发现我们希望 \(x\) 的 \(1\) 尽量往后放,于是令 \(x = l\) 就是对的。然后考虑 \(x,y\) 位数相同的情况,容易证明是不优的。
- 若 \(l,r\) 在二进制下位数相差超过 \(1\)。显然我们总是令 \(y = 2^k\),考虑 \(x\) 的取值,手玩发现位数多是不优的,而且我们总是取 \(x = 2^p\),所以这个 \(p\) 肯定越大越好,于是 \(y = 2^k,x = 2^{k-1}\) 就是对的。
那么做完了。后两种情况放在一起算,手玩发现 \(k(k+1)\) 位必定会出现循环。用 \(k(k+1)\) 当循环节就是对的。时间复杂度 \(O(tn)\)。
7.23 训练赛(F、J)
G 命运石之门的选择
神秘。
首先考虑根节点只有一个儿子的情况,此时只能从下往上选,只关心 \(n\) 的奇偶性,平凡。
考虑根结点至少有两个儿子的情况,我们在某个儿子 \(c\) 里选了点 \(u\),那么双方必定只会在 \(c\) 的子树 \(T_c\) 里选,否则 lca 就到根了,这是显然的。
那么每个子树都是独立的,对于每个子树分别考虑。现在要思考什么时候会被规则强制跳出该子树。
容易想到如果对于某个深度,这一层子树内只有一个点,子树外却还有其它点,这个时候后手就会强制跳到子树外,先手必胜。我们称这种点为关键点。
那么如果某个点为关键点,且这个点所在的子树包含深度最深的起始点,拿到这个点的先手就必胜。然后拿到这个点的先后手显然只跟这个点的子树大小的奇偶性有关。
那么就会做了。枚举每棵子树,从下往上找到第一个关键点,判断是先手必胜或后手必胜。如果有一棵子树是先手必胜,那么先手显然可以选这棵子树来让他必胜。
然后考虑怎么实现。维护每个点深度,子树大小,子树内最大深度,全局最大深度,每个深度有多少个点。在做每棵子树的时候,维护这棵子树内每个深度点的个数即可,这个可以差分,加完再减回去。那么每个点只需要维护常数次,时间复杂度 \(O(n)\)。
L 样品检测
神了。
考虑二进制分组,把样品编号写成二进制。对于每一位把该位为 \(0\)、该位为 \(1\) 的放在一起分别检测。由于 \(2^{10} > 1000\),至多 \(20\) 次就可以找到只有合法样品在的集合,在集合里二分即可。
然后前面的询问我们又确定了两个编号的每一位是否相同,那么做完了。
7.24 训练赛(C、D、L)
I「I」nan desu
神秘计数。
考虑枚举中间列 \(j\),这样对于这一列,我们得到了若干连续段。对于每个连续段显然可以单独做,我们对每个点维护往左 / 右能延长的最大半径 \(r\),那么这个段的贡献就相当于任取两个不相邻的行 \(i,k\),贡献是 \(\min(r_{i,j},r_{k,j})\)。那么对于每个连续段,内部按 \(r\) 排序,用 bit 维护贡献就是对的。当然也可以容斥。时间复杂度 \(O(n^2\log n)\)。
J Stop, Grid Please No More
容易想到答案是 \(\max((n-2)m,(m-2)n)\) 但是这样 WA 了。这个东西显然可以当下限,考虑更好的划分。手玩可以发现舍弃四个角的 \(1\times 2\) 的格可以做到 \(nm - 8\),前提是 \(\min(n,m) \ge 4\)。
K NTT
根据费马小定理,有 \(x^{p-1} \equiv 1(\bmod p)\)。考虑把 \(x^k\) 写成这个形式。有 \(k = (p-1)q + r\),那么 \(x^k = x^{(p-1)q} \times x^r \equiv x^r(\bmod p)\)。那么 \(x^k \equiv x^{k \bmod (p-1)}\),做完了。注意把 \(x\) 弄成正的再求值。
M Until next time, SCNUCPC!
神秘贪心。
记 \(d_i = p_i - p_{i-1}\),代价就是 \(\sum p_id_i = \sum \frac{1}{2} (p_i^2 - p_{i-1}^2 + d_i^2) = \frac{1}{2}(n^2 - 1 + \sum d_i^2)\)。只需最小化 \(\sum d_i^2\)。
根据均值不等式,对于一个能放的连续段,我们总是均匀地放 C。考虑刻画这个过程,记 \(f(m,p)\) 表示在长度为 \(m\) 的连续段里放 \(p\) 个 C 的最小代价。考虑这个怎么求。
那么相当于把连续段分成 \(p+1\) 段,由于是均匀地分,分出来的段长度为 \(\frac{m}{p+1}\) 和 \(\frac{m}{p+1}+1\),其中 \(m \bmod (p+1)\) 是后者的段数。那么贡献是好算的。
然后用大根堆维护 \(f(m,p) - f(m,p+1)\) 的值,取出 \(k\) 次即可。时间复杂度 \(O(k\log n)\)。
7.27 训练赛
B Bus Game
人类吗。
\(n \le 20\) 考虑直接状压,每个点只有两种状态,选了或没选,再记录一下先后手。那么 Alice 从后继 max 转移,Bob 从后继 min 转移即可。限制的话可以预处理出二进制数 \(sta_i\) 表示要选 \(i\) 的话那些点不能选。输出方案的话就正着推一下。时间复杂度 \(O(n2^n)\)。
E Simple Math
爆了。退役了。
记 \(99999 \cdots = 10^m - 1\),那么有 \(x \mid 10^m - 1\),即 \(10^m \equiv 1(\bmod x)\)。考察这个方程的可解性:
- 若 \(\gcd(10,x) = 1\),由欧拉定理知若 \(a,n\) 互质,有 \(a^{\phi(n)} \equiv 1(\bmod n)\),令 \(m=\phi(x)\) 即为一组合法解。
- 否则,\(2\) 或 \(5\) 为 \(x\) 的质因子。容易证明 \(10^m-1\) 不含 \(2,5\) 这两个质因子,因此无解。
综上,若 \(\gcd(10,x)\ne 1\),不存在。否则令 \(k = \displaystyle \frac{10^{\phi(x)}-1}{x}\) 即为答案。
M Little t's GCD
有点牛这个题。
推式子得到 \(W(L,R) = R^2 - (L-1)^2\)。考虑一下暴力 dp,\(f_i\) 表示前 \(i\) 位的答案。枚举 \(j\) 进行转移,\(f_i = \max(f_{j-1} + [i^2 - (j-1)^2] \times \gcd(a_j,a_{j+1},\cdots a_i)) - P\),其中 \(j \in [1,i]\)。
移个项发现我们关心的是 \(f_{j-1} - (j-1)^2\gcd(a_j,\cdots a_i)\),这个好像很难用大数据结构去维护,考虑一个结论:
固定右端点 \(i\),那么向左延伸的 \(\gcd(j,i)\) 至多形成 \(\log(V)\) 个值相同的连续段,这是因为 gcd 的衰减是很快的。
于是对于 \(i\) 考虑维护这个连续段。维护 \((L,R,v,W)\) 表示这个连续段为 \([L,R]\),\(j\in [L,R]\) 满足 \(\gcd(a_j,\cdots a_i) = v\),\(f_{j-1} -(j-1)^2v\) 的最大值为 \(W\)。
然后当 \(i \to i+1\) 时,进行如下维护:
- 将所有连续段的 \(v \to \gcd(v,a_i)\)。
- 若某段的 \(v\) 改变,暴力维护 \(W\)。这是因为 \(W\) 依赖 \(v\)。
- 对相同 \(v\) 进行合并。
维护完之后枚举所有连续段暴力维护 \(f_i\) 即可。时间复杂度大概是 \(O(n\log V)\)。
7.28 edu 训练(F)
E Sum of Digits (and Again)
首先容易发现这个数字和衰减是很快的,大概三四次就能结束。
一开始卡在了怎么判断能否凑出原始的数 \(X\),这个 \(X\) 很难搞,考虑枚举它衰减过一次的数,显然在 \(0 \sim 9 \times 10^5\) 之中。
然后进行暴力衰减之后就很好判原始的 \(X\) 能不能凑出来了。还是挺妙的,时间复杂度大概是 \(O(10n)\)。
7.29 训练赛(J、A)
这场真爆了。
H 周二会员日
把浮点数转成整数后做即可。
G 卡卡数
打表发现答案是 \(x10^{x-1}\)。补个证明。
我们把前导零补上,那么每个数都有了 \(x\) 位,一共 \(10^x\) 个 \(x\) 位数。然后这 \(x\) 位每一位都有 \(0\sim 9\) 共 \(10\) 种可能,且每一位 \(0\sim 9\) 的出现次数相等。那么一共 \(x10^x\) 个数字位,每一位是 \(\frac{1}{10}\) 的概率出现 \(1\)。答案就是 \(\frac{x10^x}{10}\)。
E 乐乐的杏花
虽然是 hard 但是挺好想?
想到维护每个点到乐乐的位置的距离就做完了。这个是容易用 sgt + dfn 维护的。然后再维护一棵 sgt,对于某个点如果它花开了就是真实距离,否则就是极大值。这样在维护距离时两棵 sgt 可以一起维护。时间复杂度 \(O(q\log n)\)。
M 六个核桃
一开始看成 \(\max\) 了,没绷住。
上界显然是 \(nm\)。考虑咋达到这个上界,你容易想到一个贪心策略,就是将原排列向右循环移位 \(m\)。交上去发现 wa 了。手玩一下发现这个策略在 \(m \le \frac{n}{2}\) 时是对的,可以达到上界 \(nm\)。考虑一下 \(m > \frac{n}{2}\) 的时候咋做。
这个时候难以达到上界,我们希望尽量多的位置取到 \(m\)。那么在前 \(n - m\) 个位置,构造 \(m + 1 \sim n\),在后 \(m\) 个位置,构造 \(1 \sim n - m\),这样这两部分可以取到 \(m\)。对于中间的部分,逆序放显然为最优。
这个只能感性理解,把中间的数字放在左 / 右边不会让答案更优。
C 圆桌会议
神秘。
考虑一个挺牛的构造。我们记 \(k = \frac{n}{3}\),然后把数分成三段:\([1,k],[k+1,2k],[2k+1,3k]\) 以及剩下 \(n\bmod 3\) 个数。
然后我们这么构造:
你会发现这样中位数就都来自 \([k+1,2k]\),中位数个数压缩到 \(k\) 个左右。答案只会是 \(k/k+1/k+2\)。
B 最大数码 2
\(r - l < 9\) 的直接暴力算。否则第一问答案肯定是 \(9\),考虑第二问:
- 若 \(l,r\) 位数相同,答案显然是离 \(l\) 最近的含 \(9\) 的数。
- 若 \(l,r\) 位数不同,答案的形式是 \(1000\cdots 9\),那么枚举 \(0\) 的个数做即可。注意可能存在 \(l,r\) 位数不同但 \(1000\cdots 9\) 也不存在的情况。此时答案显然与第一种情况相同。
L 猪猪车
7.30 edu 训练
F Level Generation
显然答案具有单调性。如果边数 \(m\) 成立,那么随意断掉一条边,\(m - 1\) 也成立。于是可以二分这个最大边数 \(m\),那么变成存在性问题。
我们希望割边的数量尽量少,那么割边数量显然就是下限 \(b = \lceil \frac{m}{2} \rceil\)。这样得到 \(n - b\) 个连通块,然后我们需要在这些连通块内部构造出 \(m - b\) 条边,容易想到单个连通块内点数越大越好,于是构造点数为 \(n-b,1,1,\cdots\) 的连通块,构造出来的最大边数就是 \((n-b)(n-b-1)/2\)。那么判断是否 \(\ge m-b\) 即可。
七月末的训练盛宴(I、D、G、M)
J 莲的简单题
我与构造不共戴天。
容易想到给每个数乘个质数,样例也很好的提示了。注意质数需 \(> n\)。
B 最短路图
把 \(dis_1\ne 0\) 判掉。
把 dis 从小到大排序。考虑一个点 \(r\),假设最短路树上其前驱节点为 \(l\),那么显然有 \(dis_r = dis_l + w(l,r)\)。那么我们需要一条长度为 \(dis_r - dis_l\) 的边挂在 \(l,r\) 之间。你发现这样每个点和边就形成了匹配关系,跑一遍二分图最大匹配就是对的。时间复杂度 \(O(n^3)\)。由于可以重边,剩下的边只要长度 \(\ge\) 某条边的长度,就可以扔上去。那么无解的情况就是我们需要的边的长度 \(>\) 给定的最小边的长度,此时这条边挂不了。
M Maximize the total of maximum
Hard。
首先 \(k\) 次操作肯定都要用掉。有一个结论是我们肯定是对同一个 \(a_i\) 进行操作。
证明不会,摘自题解:
设你对下标为 \(i\) 的数进行了 \(a\) 次操作,对下标为 \(j\) 的数进行了 \(b\) 次操作。
如果我们此时把全部的 \((a+b)\) 次操作全部进行在 \(i\) 上或者 \(j\) 上(此行为称之为一次“合并”),可以发现,这 \((a+b)\) 次操作对左端点在 \([1,i]\) 且右端点在 \([j,n]\) 的以及被区间 \([i + 1,j −1]\) 包含的所有区间的贡献是不变的,所以我们只需要考虑仅包含 \(i\) 的区间和仅包含 \(j\) 的区间。
记 \(c_l\) 为将 \(l\) 次操作应用在 \(i\) 上对答案产生的贡献,\(d_l\) 为将 \(l\) 次操作应用在 \(j\) 上对答案产生的贡献,显然,序列 \(c\) 和序列 \(d\) 都是非严格单调递增的。若 \(c_a\ge d_b\) ,那么将 \((a+b)\) 次操作全部进行在 \(i\) 上肯定是不劣的;若 \(c_a<d_b\),同理可知,将 \((a+b)\) 次操作全部进行在 \(j\) 上肯定是不劣的。证明完毕。
ok 那么显然枚举 \(a_i \to a_i + k\),然后大力分讨贡献。
显然只考虑包含 \(i\) 的区间。区间分为两类,一类区间和 \(\in [c-k,c]\),我们关心这类区间的区间和之和。另一类区间和 \(< c - k\),我们关心这类区间的个数。
考虑求第一类区间的贡献。考虑容斥,记 \(S\) 表示所有区间和在 \([c-k,c]\) 内的区间的区间之和。维护 \(pre_i\) 表示区间端点被 \([1,i]\) 包含的,区间和在 \([c-k,c]\) 内的区间的区间之和,同理 \(suf_i\) 表示区间端点被 \([i,n]\) 包含的。那么贡献就是 \(S - pre_{i-1} - suf_{i+1}\)。然后 \(pre_i,suf_i\) 容易用 ds 维护。
第二类区间也是同理的。那么做完了。
浙公网安备 33010602011771号