暑期集训

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]\) 是排列,那么有:

  1. 最大值是区间长度。
  2. 区间无重复元素。记 \(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)

link

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)

link

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\) 个数。
然后我们这么构造:

\[1,k+1,2k+1,2,k+2,2k+2 \cdots k,2k,3k, 3k+1,3k+2 \]

你会发现这样中位数就都来自 \([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 猪猪车

LINK

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 维护。
第二类区间也是同理的。那么做完了。

posted @ 2026-07-06 13:49  RainyRadio  阅读(4)  评论(0)    收藏  举报