2024年11月随便做做

十月太摆了没有随便做做环节。

测试题目选集

20241102 - D. 有理数

相当于求:

\[\prod_{1\le i<j\le n} \frac{b_ib_j}{\gcd (b_ib_j,b_ia_j-b_ja_i) } \]

为了方便书写,记 \(a\leftarrow b_i,b\leftarrow a_i,c\leftarrow b_j,d\leftarrow a_j\)。实际上就是对 \(\gcd (ac,ad-bc)\) 做分析。

首先,应该有 \(\gcd (a,b)=\gcd (c,d)=1\),否则可以先自己化简自己。之后考虑这一个式子实际上是有积性(对于 \(a,c\) 而言)的,因此对于每个素数 \(p\) 单独考虑。记 \(a=a'p^{k_1},b=b'p^{k_2}\),同时要求 \(a'\nmid p,b'\nmid p\),当然应该有 \(k_1,k_2>0\)

如果 \(k_1\ne k_2\),则不妨令 \(k_1<k_2\),那么原式就是 \(\gcd (ac,ad-bc)=p^{k_1}\gcd (a'c'p^{k_2-k_1},a'd-bc'p^{k_2-k_1})\)。发现 \(\gcd(a',p)=1,\gcd(d,p)\le \gcd (d,a')=1\),同时因为 \(k_2-k_1>0\),所以 \(bc'p^{k_2-k_1}\)\(p\) 的倍数。因此 \(a'd-bc'p^{k_2-k_1}\not\equiv 0 \mod p\),因此对于 \(p\) 来说贡献就是 \(p^{k_1}\)

否则,记 \(k=k_1=k_2\),则先提出 \(p^k\),剩余 \(\gcd(a'c'p^k,a'd-bc')\)。而在只考虑 \(p\) 的贡献下,就应该是:

\[\begin{aligned} &\prod_{k'=1}^k p^{[a'd-bc'\equiv 0\mod p^{k'}]} \\ =&\prod_{k'=1}^k p^{[\frac{b}{a'}\equiv\frac{d}{c'}\mod p^{k'}]} \end{aligned} \]

以上所有的情况都可以用桶实现。其中一种容易想到的实现的时间复杂度是 \(O(V\log_2 V+n\log_2^2 V)\)

20241105 - D. 牛仔

实际上比较简单,关键实际上是转化成非牛仔序列之后对于每个出现的匹配的计算方案数。同时可以注意到每个数是等价的,所以用 \(A\) 去匹配时,只需要乘 \(\frac{(k - pre)!}{k!}\) 就行了,其中 \(pre\)\(A\) 中最长的前缀使得没有重复的数。

20241106 - D. 盼君勿忘

给定一棵树。每个点有颜色 \(0\)\(1\)。每次将树上相邻且颜色相同的两个点的颜色同时改变,记 \(s_i\)\(i\) 的初始颜色,\(t_i\) 为最终颜色,\(f(s,t)\) 为颜色序列 \(s\) 变为 \(t\) 的最少操作数,无法做到则为 \(0\)。现在某些 \(s_i,t_i\) 上为 ?,表示颜色未知。求对于所有可能的 \(s,t\)\(f(s,t)\) 之和对 \(10^9+7\) 取模。

\(n\le 5\times 10^5\)

首先感觉要求相邻且相同的点同时变色的条件非常令人没有头绪。这时在树上有一个很棒的转化,就是将奇数深度的点的颜色全部取反。这样操作之后,原本的条件变成了交换两个相邻不相同的点的颜色,当然因为有操作数最小的要求,实际上就是交换两个相邻点的颜色。所以操作后,\(s_i\leftarrow s_i \oplus [2\nmid dep_i]\)\(t_i\) 同理。当然 ? 不需要管。

然后放一放题目,将这一系列操作变得简单可理解:从初始状态 \(s\) 开始,每次其实就是移动一个颜色为 \(1\) 的点,移动到 \(t_i=1\) 的点上和其抵消。然后做一下经典等价变换,相当于是 \(s_i=1\)\(t_i=1\) 黑白两种棋子,棋子只能往上移,黑白棋子碰在一起会抵消。这样似乎就变得明朗多了,记 \(z_u=|\sum_{v\in subtree(u)} s_u-t_u|\),会发现答案实际上就是 \([z_1=0]\sum_{u} z_u\),因为可以合并的一定在子树内抵消完了,往上走的一定是未被抵消的棋子,于是对每个 \(u\to father_u\) 的边计算贡献即可。然后就可以解决已知 \(s,t\) 的情况了。值得注意的是必须要有 \(z_1=0\) 的条件,不止是因为合不合法的问题,这一步其实也是后续的关键。

\(s\) 中问号个数为 \(A\)\(t\) 中为 \(B\),已知部分的 \(\sum_u s_u-t_u=C\)。考虑对于一个子树 \(u\) 计算 \(z_u\) 的贡献,在其中的 \(s_v\) 为问号的个数为 \(x\)\(t_v\) 为问号的个数为 \(y\),子树内已知部分的 \(\sum_{v\in subtree (u)} s_v-t_v=z\)

那么可以枚举 \(i,j,k,l\) 分别为子树内外 \(s,t\) 中问号为 \(1\) 的个数。那么 \(u\) 对答案的贡献为:

\[\sum_{i\le x}\sum_{j\le y}\sum_{k\le A-x}\sum_{l\le B-y}[C+i-j+k-l=0]{x\choose i}{y\choose j}{A-x\choose k}{B-y\choose l}|z+i-j| \]

进行一步不太显然的转化,考虑枚举 \(p=i-j,q=k-l\) 来代换:

\[\begin{aligned} &\sum_{i}\sum_{p}\sum_{k}\sum_{q}[C+p+q=0]{x\choose i}{y\choose i-p}{A-x\choose k}{B-y\choose k-q}|z+p| \\ =&\sum_{i}\sum_{p}\sum_{k}\sum_{q}[C+p+q=0]{x\choose x-i}{y\choose i-p}{A-x\choose A-x-k}{B-y\choose k-q}|z+p| \\ =&\sum_{p}\sum_{q}[C+p+q=0]{x+y\choose x-p}{A+B-x-y\choose A-x-q}|z+p| \\ =&\sum_{p}{x+y\choose x-p}{A+B-x-y\choose A-x+C+p}|z+p| \end{aligned} \]

最后一步因为 \(C+p+q=0\) 的缘故可以将原式转化成一个可以 \(O(n)\) 计算的式子。所以得到了一个 \(O(n^2)\) 的做法。

考虑进一步优化:记 \(P=x-p,X=A+B,Y=A+C\),有代换:

\[\begin{aligned} \sum_{P}{x+y\choose P}{X-x-y\choose Y-P}|z+x-P| \end{aligned} \]

到这里似乎就明朗多了,实际上每个 \(u\) 求的是一个类似的的多项式。记 \(f(x,y)=\sum_{i}{x\choose i}{X-x\choose Y-i}|y-i|\)。那么答案实际上是 \(\sum_{u} f(x_u+y_u,z_u+x_u)\),其中 \(x_u,y_u,z_u\) 对应上文对于 \(u\) 求贡献一节的 \(x,y,z\)

\(f(x,y)\) 进行适当的改写:

\[\begin{aligned} f(x,y)=&\sum_{i}{x\choose i}{X-x\choose Y-i}|y-i| \\ =&\sum_{i}{x\choose i}{X-x\choose Y-i}(i-y)+2\sum_{i\le y}{x\choose i}{X-x\choose Y-i}(y-i) \\ =&-y {X\choose Y}+x\sum_i {x-1\choose i-1}{X-x\choose Y - i}+2\sum_{i\le y}{x\choose i}{X-x\choose Y-i}(y-i) \\ =&-y {X\choose Y}+x{X-1\choose Y-1}+2\sum_{i\le y}{x\choose i}{X-x\choose Y-i}(y-i) \end{aligned} \]

前面可以 \(O(1)\) 计算,将后面单独提出来:

\[\begin{aligned} &\sum_{i\le y}{x\choose i}{X-x\choose Y-i}(y-i) \\ =& y\sum_{i\le y} {x\choose i}{X-x\choose Y-i}-x\sum_{i\le y}{x-1\choose i-1}{X-x\choose Y- i} \\ =& y\sum_{i\le y} {x\choose i}{X-x\choose Y-i}-x\sum_{i< y}{x-1\choose i}{X-x\choose Y-1- i} \end{aligned} \]

前后本质上都是另一个多项式 \(g(X,Y,x,y)=\sum_{i\le y} {x\choose i}{X-x\choose Y-i}\)。于是可以把其替换为 \(y\cdot g(X,Y,x,y)-x\cdot g(X-1,Y-1,x - 1,y-1)\)

因为本质上求法是一样的,所以在下文中将用 \(g(x,y)\) 代表实际上的 \(g(X,Y,x,y)\)

但是 \(g(x,y)\) 仍然并不好求。这时可以考虑计算 \(g(x+1,y)-g(x,y)\)\(g(x,y+1)-g(x,y)\) 的值,前者考虑组合意义得出,而后者十分显然。

\[g(x+1,y)-g(x,y)={x\choose y}{X-(x+1)\choose Y - (y+1)} \\ g(x,y+1)-g(x,y)={x\choose y+1}{X-x\choose Y-(y+1)} \]

于是可以由 \(g(x,y)\) 得到 \(g(x,y+1)\)\(g(x+1,y)\)

然后可以使用莫队做到 \(O(n\sqrt n)\)

而有一个更优的做法,就是重链剖分之后对每个链单独计算,因为重链链上的是同阶的所以时间复杂度为 \(O(n\log_2 n)\)。这里重链剖分实际上应该对 \(x_i+y_i,z_i+x_i\) 做,但是因为限制严格小于二倍子树大小,所以直接重剖 size 就可以了。

Miscellaneous

[AGC022D] Shopping

神秘题目,比较酷。

首先发现对于 \(t_i\ge2L\)\(t_i\) 可以直接将 \(t_i\lfloor\frac{t_i}{2L}\rfloor\) 加入答案并将 \(t_i\)\(2L\) 取模。然后只考虑 \(t_i \ne 0\)\(i\)

考虑如何优化这个策略。首先简化操作,如果从一个点出来之后往某个方向走到最边上之后折返回来经过这个点,那么选择在后面上车。因此得到了好像更简单的操作序列。之后在操作序列中将花 \(2L\) 时间的点去掉之后,会发现每次从一个点出来一定会改变方向,这个序列(如果存在的话)一定是第一次会往左走时进,往右走时出,最后一次和第一次的方向一定相反,这个序列长度为偶数,贡献为长度除以 \(2\) 乘以 \(2L\),因为实际上是第 \(2i-1\) 个和第 \(2i\) 个配对优化一个 \(2L\)。这启发出了更进一步,将(可以左走变右走的点)和(可以右走变左走的点)进行尽量多的配对,因为每个配对可以优化一个 \(2L\)。似乎是一个很难的问题。

这时构建一种思路,对于每个 \(i\),直接花 \(2L\) 的时间走,这样时间就是 \(2L\cdot (n + 1)\) 的。之后对于剩余的每个非 \(0\) 的位置,记 \(l_i= [2x_i\ge t_i]\) 表示车下了人之后往左走再回来是否可以直接接上,\(r_i\) 同理。\(l_i=1\) 说明可以右走变左走,\(r_i\) 同理。实际上我们就是找 \(i<j,l_i=r_j=1\),最大的不交 \((i,j)\) 对数,因为通过一些思考得到对于 \(\{(i,j)\}\) 一定存在 \(|\{(i,j)\}|=|\{(i',j')\}|\)\(\{(i',j')\}\) 可以拼出一个顺次的操作序列。

考虑观察性质:

  • \(l_i=r_i=0\) 时,无法优化。

  • \(l_i=1,r_i=0\) 时,\(2x_i\ge t_i > 2L - 2x_i\),得到 \(x_i\ge L/2\)

  • \(l_i=0,r_i=1\) 时,同理可得 \(x_i\le L/2\)

  • \(l_i=r_i=1\),可以随便匹配。

于是发现 \(l_i+r_i=1\) 的匹配一定是和 \(l_j=r_j=1\) 的合并,而 \(l_i=r_i=1\) 的也可以自己合并,于是分开贪心匹配就可以了。

有个小细节是,\(n\) 一定存在一种最优操作序列使得它不会被匹配,因为若 \(r_n=1\) 可以自己少一次 \(2L\)

Submission #59511721 - AtCoder Grand Contest 022

NIKKEI Programming Contest 2019 F - Jewels

题意:每个物品有颜色和权值,每个颜色要么不选,要么至少选两个,对 \(i=1,\cdots,n\) 分别求出选恰好 \(i\) 个的最大权值。

将每个颜色中前两大的放在一起,权值取平均数,称为对子,剩余的称为单个,从大到小排序之后求答案 \(f(x)\)。如果前缀恰好可以拼出 \(x\),那么就直接是答案。

重点就是拼不出 \(x\) 的时候,发现一定可以拼出 \(x-1\),那么剩余不能放进去的是一对。然后直觉上似乎已经放进去的 \(x-1\) 中取出来的数不会很多。先尝试分类讨论:

  • 不去掉数,加入之后一个合法的(自己颜色对应的对子已经被加入)对子已经加入的单个。
  • 去掉一个之前的单个。此时后面可以加入两个合法单个或者加入一个对子。但是显然加入两个单个是不优于对子的,因为 \((x,x+1)\) 处的对子一定大于两个它后面的单个之和。所以策略应该是去掉单个之后直接加入 \((x,x+1)\) 处的对子。
  • 去掉两个数。一种情况是去掉两个单个之后加入一个对子以及一个合法单个,但是这个合法单个显然小于等于去掉的两个单个中的任意一个,所以一定不优于直接去掉一个加上一对的策略。另一种策略就是去掉一个对子,加入一个对子和一个合法单个,注意到这个单个实际上必须和加入的对子同色,否则因为合法,所以必定时原本 \(x-1\) 里边的某个对子的单个,因此可以不用删去对子,直接加入这个单个即可。因此策略应该是去掉一个对子,加入同色的对子和单个。
  • 去掉三个数。首先去掉三个单个的情况可以参考去掉两个单个的情况,明显不优。所以只剩下去掉一个对子加上一个单个的情况。加入四个单个同样明显不优。考虑加入一个对子和两个单个同样不优,因为如果要加对子那么就先将单个去掉,这是就变成了前面的对子替换后面两个单个,明显不优。那么只剩下加入两个对子。考虑这样同样不优,同之前一样先去掉一个单个,加入一个对子,这时剩下的操作就是去掉一个对子再加入一个对子,显然不优。

通过去掉三个数的情况似乎发现了一些性质。如果去掉的集合里边有单个而加入的集合中有对子,那么可以去掉这个单个再加入对子。之后的替换就变成了相同数量的交换,一定不优于不换(如果加入集合还有剩余)。如果加入集合只有这个对子,情况在分类讨论中已讨论。那么就剩下去掉的集合中全为对子或者加入的集合中全为单个的情况。

加入的集合中全为单个的情况,发现加入集合的大小不会超过 \(1\),因为随便加入一个合法的单个之后,剩余部分实际上是等量的前后替换,明显不优。

去掉的集合中全为对子的情况,如果加入集合中存在一个对应对子在 \(x-1\) 前面的位置,那么显然可以变成只加入这个单个,明显不优。否则就是新加入了某些颜色的一个对子和若干对应单个,首先如果某个颜色的单个大于等于两个一定不如保留去掉集合中的对子。其次如果存在没有单个的对子,也可以替换成前面的对子。再其次如果(对子+单个)的数量大于等于 \(2\),就可以去掉两个这种形式,保留三个去掉集合中的对子。所以就只剩下去掉集合中只有一个(对子+单个)的情况,这在上文的分类讨论中已经讲过了。

因此可以发现策略只有三种:

  • 加入一个合法的单个。
  • 去掉一个单个,加入 \((x,x+1)\) 处的对子。
  • 去掉一个对子,加入一个对子和同种颜色的一个单个。

有很多数据结构都可以维护这个。

Submission #59932152 - NIKKEI Programming Contest 2019

Codeforces 2039 F1 - Shohag Loves Counting (Easy Version)

发现相当于统计一个递减序列使得前缀 \(\gcd\) 全部不同的序列个数乘上 \(2\) 的(长度\(-1\))次幂的和。

然后就可以定义出一个 dp 式子。记 \(f[t][x]\) 表示当前序列最左边也就是最小值为 \(t\),当前序列 \(\gcd\)\(x\) 时的方案数。因为 \(x|t\) 所以总共的状态数是 \(O(n\log_2 n)\) 级别的。然后考虑 \(f[D][d]\to f[t][x]\) 可以转移的条件是 \(D>t,x=\gcd(t,d),x\ne d\)。就可以写出转移式子了。注意转移中要同时乘以 \(2\),因为每次长度都增加了 \(1\),而且初值应该有 \(f[t][t]=1\) 表示序列的开头为 \(t\)。进行以下式子推导:

\[\begin{aligned} ([x|t])(f[t][x]-[t=x])/2 = & \sum_{x|d,x\ne d,\gcd(t/x,d/x)=1}\sum_{d|D}([D>t])f[D][d] \\ = & \sum_{k}[\gcd (t/x,k)=1]\sum_{kx|D} ([D>t])f[D][kx] - \sum_{x|D}([D>t])f[D][x] \\ = & \sum_{k}\sum_{d|\gcd(t/x,k)}\mu(d) \sum_{kx|D}([D>t])f[D][kx] - \sum_{x|D}([D>t])f[D][x] \\ = & \sum_{d|(t/x)} \mu(d) \sum_{d|k}\sum_{kx|D}([D>t])f[D][kx] - \sum_{x|D}([D>t])f[D][x] \\ = & \sum_{dx|t} \mu(d) \sum_{dx|kx}\sum_{kx|D}([D>t])f[D][kx] - \sum_{x|D}([D>t])f[D][x] \\ = & \sum_{dx|t} \mu(d) \sum_{dx|kx} g(kx) - g(x) \\ = & \sum_{dx|t} \mu(d) F(dx) - g(x) \\ \\ F(x)= &\sum_{x|d}\sum_{d|D} ([D>t]) f[D][d] \\ \\ g(d)= &\sum_{d|D}([D>t])f[D][d] \end{aligned} \]

发现从后往前扫描 \(t\) 求出 \(f\) 和同时更新 \(F,g\) 的时间都是 \(O(n\log_2 ^2n)\)

(其实应该是 \(O(\log_2n\cdot\sum_{i=1}^n \sigma(i))\),其中 \(\sigma(i)\) 表示 \(i\) 的因数个数)

Submission #293159916 - Codeforces

[NOI2012] 骑行川藏

感觉不是很可做啊。首先似乎有一种通法叫拉格朗日乘子法。但是不会。

考虑一个感觉对的策略,把体能 \(E\) 分成无限小份 \(\Delta\),并让每段的初始速度为 \(v_i=\max (v_i', \Delta)\),时间为 \(t_i=\frac{s_i}{v_i}\),使用体能 \(e_i\) 用公式计算。记 \(T_i(e)\) 表示第 \(i\) 段路使用 \(e\) 的体能时,花费的最小时间,可以猜测有:\(T_i(e)\) 的导数 \(T_i'(e)\) 会随着 \(e\)\(0\) 到无限的增长中从极小的负数开始不断变大靠近 \(0\)。然后就变成了将每小份 \(E\) 分到某个第 \(i\) 段上,使得时间加上 \(T_i'(e_i)\),并且 \(e_i\) 加上这个小份。显然选最小的那个 \(T_i'(e_i)\) 就可以了。

因此得到一个优秀的结论:最终情况下的体能分配 \(e_i\) 下所有数的 \(T_i'(e_i)\) 应该大于等于某个数 \(d\) 且大于时 \(v_i=v_i'\)。那么根据这个 \(d\) 实际上可以唯一得到 \(v_i,e_i\) 。根据这个 \(d\) 刻画出一个函数 \(E_0(d)\) 表示此时的 \(\sum e_i\)。会发现 \(d\) 越大 \(E_0(d)\) 越大,因此找到 \(E_0(d)=E\)\(d\) 就可以找到 \(v_i\) 了。所以可以二分 \(d\)

那么进入数学时间。首先是 \(T_i'(e_i)\),应该如下:

\[\frac{\mathrm d t}{\mathrm d e} = \frac{\mathrm d t}{\mathrm d v} / \frac{\mathrm d e}{\mathrm d v} =\frac{-2s}{v^2}/(2k(v-v'))=\frac{-s}{2kv^2(v-v')} \]

满足猜测。同时可以通过上式 \(\frac{-s}{2kv^2(v-v')}=d\) 得到 \(v\),在 \(v\ge v',v>0\) 时若无解则 \(v=v'\),解方程也可以二分。

然后似乎就做完了。细节见代码。

提交记录 #2209472 - LibreOJ

本文作者:saubguiu

本文链接:https://www.cnblogs.com/imcaigou/p/18533907

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   saubguiu  阅读(27)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑