上海市大学生程序设计竞赛 - 七月赛 题解

转送门

A. 狗吃骨头

\(a_n\) 表示还有 \(n\) 只狗准备去吃骨头时骨头的数量 \(a_m\) 就是我们要求的答案。
由题意可以得到递推关系

\[(a_{i} -1)\frac {m-1} m = a_{i-1} \]

(\(-1\) 代表吃一根,\(\frac {m-1} m\) 代表吃一份),利用待定系数法,转换为指数数列

\[a_n + m - 1 = {m\over m-1} (a_{n-1} + m - 1) \]

\(b_n = a_n + m - 1\),即 \(b_n = {m\over m-1} b_{n-1}\),立即有

\[b_n = ({m\over m-1})^{n-1} b_1 \]

由于要满足吃骨头的规律,\(a_n\) 必须满足 \(m | (a_n - 1)\),并且\(a_n,b_n\)必须是整数。

\(m>2\) 时,由于 \(m \perp (m-1)\) (i.e. \(m\)\(m-1\) 互质),因此为了保证\(b_1\sim b_m\) 是整数,必须有 \(b_1 = K (m-1)^{m-1}\) 其中 \(K\) 是正整数。

此外,因为最后一条狗也要能够按照规律吃骨头,因此 \(m|(a_1-1)\),代入\(a_1 = b_1 - m + 1\)

\[m \Big|\Big( K(m-1)^{m-1} - m \Big) \]

仍然由于\(m \perp (m-1)\),由 Bezout 定理,\(m|\gcd(K(m-1)^{m-1},m)\),因此最小的 \(K=m\)。故 \(b_1=m(m-1)^{m-1},b_m = ({m\over m-1})^{m-1}b_1 =m^m\)

代入式子,\(a_m = b_m - m + 1 = m^m - m + 1\)。当\(m=2\)时,递推式由于不成立,这是因为 \(a_2 = 3\) 会导致第二只狗没有足够的骨头吃,上述推导没有考虑"剩下的骨头非负"这一要求。

因此答案为

\[\begin{cases} m^m - m + 1 & m > 2 \\\\ 3 & m = 2 \end{cases} \]

注意边界情况啊,少年

音乐之城

先考虑 \(t = 0\) 的情况,此时最长的 combo 数量是 \(b_i = a_i \% x\) 的最常连续相同子段。

\(s\) 表示启动时间,不妨假设 \(s<0\),那么一个音符能够被击打到,当且仅当 \(\exists y. |y|\le t \land a_i + y \equiv s \mod x\)。那么通过枚举 \(y\) 就能计算出 \(s \mod x\) 的值,那么便求得了一个音符对应的能够被击打的 \(s\) 的集合,设为 \(I_i\)。由于\(|I_i|\le 64\),那么可以用状态压缩至一个 64 位数,记为E[i]

那么一段音符 \(l,l+1,\dots,r\) 能够被击打到,当且仅当 \(I_l \cap I_{l+1} \cap \dots \cap I_r \neq \varnothing\),这即当且仅当 \(E[i] \land E[i+1] \land \dots \land E[r] \neq 0\) (\(\land\) 表示二进制与)。因此可以通过预处理出 \(E\) 数组,并使用 st表维护区间 \(\land\) (二进制与) 。枚举一个 \(l\),那么就能够通过二分查找最远的 \(r\),使得 \(E[l] \land E[l+1] \land \dots \land E[r] \neq 0\),那么 \([l,r]\) 就是一段 combo 区间。总复杂度 \(O(n \log n + {nx \over 64})\)

地球签证

很明显 \(i\)\(\lfloor \frac i 2 \rfloor\) 构成一颗二叉树关系。 设 \(dp[i,a,b,0/1]\)表示考虑标号为 \(i\) 的子树,其中有 \(a\) 个被分为"男性",\(b\)个被分为"女性",且当前点被分为男性/女性,的最大多样性值。枚举 \(i\) 的性别,然后枚举 \(i\) 的两个儿子的性别,就能够得到转移方程。

然而 \(a+b = \text{size}[i]\)\(\text{size}\) 表示子树大小。因此只需要记录一个维度即可。设 \(dp[i,a,0/1]\) 表示考虑标号为 \(i\) 的子树,其中有 \(a\) 个被分为"男性",且当前点被分为男性/女性,的最大多样性值。那么转移方程为,同样枚举 \(i\) 的性别,然后枚举 \(i\) 的两个儿子的性别,就能够得到转移方程。树上揹包复杂度 \(O(n^2)\)

回文文回

  • 结论1: 本质不同的回文子串个数是 \(O(n)\) 的。
  • 结论2: 本质不同的回文子串一定是以某个点结尾的、最长的那个回文串。

证明:假设在原有字符串后面新加上一个字符长度变成 \(p\),那么新产生的本质不同的回文串一定是以 \(c\) 结尾的、最长的那个回文串 \(S[l\ \dots\ p]\)。任何结尾于 \(p\),且长度短于 \(S[l\ \dots\ p]\) 的回文串 \(S[l'\ \dots \ c]\),由对称性,都可以在 \(S[l\ \dots\ p]\) 中找到一个相同的回文串\(S[l\ \dots\ p'], p' = l + p - l'\),因此这个串重复出现过,不是新的"本质不同的串"。那么长度为 \(L\) 的回文串,最多只有 \(L\) 个本质不同的回文串。

  • 结论3: 设总长度为 \(N\),长度\(>\sqrt N\)的串的数量是 \(< \sqrt N\) 的。

证明:若长度 \(>\sqrt N\) 的字符串 \(\ge \sqrt N\),那么本质不同的回文串数量就会超过 \(\sqrt N \times \sqrt N = N\),与总长度为 \(N\) 矛盾。

那么用类似于 manacher 的算法处理回文串,得到的 manacher 中的辅助数组 p[i], 可以用这个计算所有可能的本质不同的回文子串,使用字符串哈希,将所有本质不同的子串的哈希值放入一个unordered_set(哈希) 中。考虑如何处理询问,使用根号分治:

  • 询问的两个字符串的长度 \(\le \sqrt N\)时: 暴力询问,一次询问复杂度 \(O(\sqrt N)\)

  • 询问的两个字符串,一个长度 \(> \sqrt N\),一个 \(\le \sqrt N\)时:枚举短串中所有的本质不同的字符串的哈希值,在长串的 unordered_set 中查询是否存在相同回文串。复杂度 \(O(\sqrt N)\)

  • 询问的两个字符串 \(A\)\(B\),两者长度都 \(> \sqrt N\) 时:直接暴力枚举 \(A\) 中所有本质不同的回文串,在 \(B\) 串的 unordered_set 中查询是否存在相同的回文串。对于 \(A\) 中所有本质不同的回文串,因此只会被拿出来"暴力匹配" \(\sqrt N\)次 (由结论3,只有 \(\sqrt N\) 种不同的 \(B\))。对于每个长字符串,只有\({N \over \sqrt N} = \sqrt N\)种查询。因此对于每个长串所有本质不同的字符串,每个本质不同回文串最多被拿出来暴力查询\(\sqrt N\)次。由于总共只有\(O(N)\)长度的串,因此总共也只会有\(O(N\sqrt N)\)次查询。

询问的时候枚举短串,然后把答案记忆化到 std::unordered_map 里,就能AC。这不是数据水,而是复杂度正确

(使用回文自动机可以避开字符串哈希,复杂度同样为\(O(N\sqrt N)\))

PS: 为了卡掉复杂度不对的做法,造数据时想办法卡满了分块的复杂度,导致一些大常数程序无法通过

研究方向

结论:一个研究方向 \((i,j,k)\) 可行,当且仅当 \(\gcd(j,k)|i\)

先假设我们只能进行一次操作(定义一次操作为若干次 improve 后再 reduce),那么 \(i\) 能化为 \(j\) 当且仅当下列方程有解:

\[ j = {i + y k \over x} \quad (x>0 \land y \ge 0 \land x,y \in \mathbb{N}) \]

\[x j - y k = i \quad (x>0 \land y \ge 0 \land x,y \in \mathbb{N}) \]

由 Bezout 定理,这个方程如果要有解,必要条件是满足 \(\gcd(j,k)|i\)。假设一组特解为 \(x_0 j - y_0 k = i\)。由通解公式得 \(x=x_0 + kt,y = y_0 + jt\) 。 令 \(t\) 足够大即得两个正整数解。因此,如果只能进行一次操作(ie. 若干次 improve 再 reduce 一次),\((i,j,k)\) 可行当且仅当 \(\gcd(j,k)|i\)

综上我们证明了,如果只能进行一次操作,那么 \((i,j,k)\) 可行当且仅当 \(\gcd(j,k)|i\)。利用数学归纳法容易证明,如果可以进行 \(\forall K. K>1\) 次操作,那么 \((i,j,k)\) 可行仍然当且仅当 \(\gcd(j,k)|i\)

因此

\[\begin{aligned} W &= \sum_{i=1}^n \sum_{j=1}^n \sum_{k=1}^n [\gcd(j,k)|i] \\ &= \sum_{i=1}^n \sum_{j=1}^n \sum_{k=1}^n \sum_{d=1}^{n} [\gcd(j,k) = d] [d | i] \\ &= \sum_{i=1}^n \sum_{d=1}^{n} [d | i] \sum_{j=1}^n \sum_{k=1}^n [\gcd(j,k) = d] \\ &= \sum_{i=1}^n \sum_{d=1}^{n} [d | i] \sum_{j=1}^n \sum_{k=1}^n [d|j][d|k][\gcd({j\over d},{k\over d}) = 1] \\ &= \sum_{i=1}^n \sum_{d=1}^{n} [d | i] \sum_{j=1}^{\lfloor \frac n d \rfloor} \sum_{k=1}^{\lfloor \frac n d \rfloor} [\gcd(j,k)=1] \\ &= \sum_{i=1}^n \sum_{d=1}^{n} [d | i] \Big(-1 + 2\sum_{j=1}^{\lfloor \frac n d \rfloor} \phi(j) \Big) \\ &= \sum_{d=1}^{n} \sum_{i=1}^n [d | i] \Big(-1 + 2\sum_{j=1}^{\lfloor \frac n d \rfloor} \phi(j) \Big) \\ &= \sum_{d=1}^n \lfloor \frac n d \rfloor \Big(-1 + 2\sum_{j=1}^{\lfloor \frac n d \rfloor} \phi(j) \Big) \\ \end{aligned} \]

利用数论分块快速求上述式子,利用杜教筛等算法可以在 \(O(n^{2 \over 3})\) 的时间内计算一次 \(\sum_{i=1}^m \phi(i)\) 的前缀和;然而在本题中,所有需要用到的 \(\phi\) 的前缀和都在第一次杜教筛算法(ie. 计算 \(\sum_{i=1}^N \phi(i)\) , cf. oi-wiki )中计算过了,因此只需要一遍杜教筛,用map把计算过的值进行记忆化,避免重复计算。总复杂度 \(O(n^{2\over 3})\)

比赛情况

本次比赛中出现了比较多的小问题,比如输入格式上下文不符、空格换行不分、题目描述不清、测试数据有误等等。这些问题都是由于我们的疏忽导致的,在这里向大家真诚道歉。

尽管我们在赛时采取了迅速有效的办法进行补救(以上问题均在 \(120\) 秒内得到妥善解决),但是对比赛的影响还是不可避免的。希望能够得到大家的谅解。尤其是对于较早遇到问题的同学,比如在"问答"中指出题目问题的同学等,请您联系我们,我们会尽可能以纪念品来向您表达歉意和感谢。

后记

感谢大家参加2023 年上海市大学生程序设计竞赛 - 七月赛,希望大家能够在比赛中有所收获。如果有任何疑问,欢迎在讨论区指正。如果你的做法更厉害或者有其他想吐槽或者讨论的,欢迎在此处评论区,或者ShanghaiTech-ACM OJ指出。

鸣谢:上海交通大学俞勇老师、华东师范大学肖春芸老师、华东师范大学汪鼎尊同学、上海科技大学科道书院汤飞龙老师、信息学院屠可伟、杨思蓓、闻天明老师的大力协助。没有你们本场场比赛难以顺利进行。此外,感谢上海科技大学黄磊、曹宇涵同学,清华大学彭思进、高子翼同学,北京师范大学香港浸会大学联合国际学院李欣泽同学和北京理工大学周行健同学对于本套试题的贡献。此致,

敬礼!祝各位选手前程似锦!


上海科技大学程序设计竞赛社团

地址:上海市浦东新区华夏中路393号上海科技大学信息学院 1B-205 室

邮箱: [email protected]

网址: acm.shanghaitech.edu.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章