Nanako
2020-07-23T16:21:07.250Z
http://tanakarino.cn/
Nanako
Hexo
[20200705] 2017-2018 CCPC, Qinhuangdao
http://tanakarino.cn/2020/07/20/20200705-2017-2018-CCPC-Qinhuangdao/
2020-07-20T08:58:22.000Z
2020-07-23T16:21:07.250Z
<h1 id="Review"><a href="#Review" class="headerlink" title="Review"></a>Review</h1><p>开场跟榜看 L,水题不讲,<strong>10min1A</strong>,rank10<del>(什么嘛我手速还挺快的)</del>。跟榜看 C,字符串分类讨论一下,<strong>33min1A</strong>,rank11<del>(什么嘛我手速还挺快的)</del>。跟榜看 E,还是字符串分类讨论一下,但是漏情况了交了发 WA……<strong>57min2A</strong>,rank18<del>(什么嘛我手速还挺快的)</del>。</p>
<p>到目前为止都还算顺利,但是接下来的 M 我们开始三人互演。首先我们发现安全的程度和到原点的距离有关,但是达到一定临界值之后就一样安全了。一开始我想当然设了个临界值 <code>lim = R - r</code>,WA 了之后我认真画了个图改成了 <code>lim = max(0, R - 2 * r)</code>,又 WA 了之后 Luowaterbi 认真画了个图告诉我是 <code>lim = max(0, 2 * r - R)</code>,又 WA 了之后我才发现其实这是小圆半径不同取值范围时的两种情况,所以改成 <code>lim = abs(R - 2 * r)</code> 就过了,<strong>109min6A</strong>,是的,这题交了六发才过,过的时候 rank 已经掉到 66 了。</p>
<p>A 很有趣,是个好题,讨论了一会之后离散化过掉了,<strong>184min2A</strong>。G 讨论了一会之后我发现是从高位到低位贪心,由于需要高精度用 Java 写了一下,不知道 BigInteger 怎么算的内存,交了好几发 MLE 才过,<strong>259min5A</strong>。</p>
<p>过完 A 和 过完 G 的时候 rank 都是 44,但是最后又掉到 54 / 254 了。什么时候能进个 Au 线呢……</p>
<h1 id="Solution(咕咕)"><a href="#Solution(咕咕)" class="headerlink" title="Solution(咕咕)"></a>Solution(咕咕)</h1>
[20200614] 2016-2017 ACM-ICPC, Asia Shenyang Regional Contest
http://tanakarino.cn/2020/07/20/20200614-2016-2017-ACM-ICPC-Asia-Shenyang-Regional-Contest/
2020-07-20T08:07:33.000Z
2020-07-20T08:52:06.456Z
<h1 id="Review"><a href="#Review" class="headerlink" title="Review"></a>Review</h1><p>开场 Luowaterbi 告诉我 I 是 sb 题,让输出四个数的和,然后我就直接 ull 冲了上去 WA 了一发,才发现最大值正好可以卡爆 ull……这种题意义何在啊!!!加了个特判过了,<strong>13min2A</strong>。然后看榜好像 K 也很签到,于是写了一下,<strong>22min1A</strong>,由于手速还可以所以 rank28。</p>
<p>接下来的 L 和 F 难度好像差不多,我们先读了 L,接着队友又去读 F 了。我对着 L 一顿口胡,最后突然想到正解才发现口胡的全是假的,于是交了一发过了,<strong>60min1A</strong>,rank 掉到 31。然后我们对着 F 一顿推,但是没啥好的结论。推着推着,Luowaterbi 突然告诉我这个 F 居然有某种奇妙深刻的递推关系。但是数据范围又要求高精度,<del>所以我又开始展示我的垃圾 Java 水平</del>,这么简单的代码写了好久,然后还连交了四发 WA,debug 了半天之后突然发现是因为文件创建在一个 package 里,所以 Intellij 自动在我的代码开头加了 package 我没发现……<strong>122min5A</strong> 之后 rank 又掉到 37,<del>又是同题数垫底了……实在是我队传统艺能……</del></p>
<p>接下来 G 和 M 难度好像也差不多,我们先读了 G,接着队友又去读 M 了。我对着 G 一顿口胡<del>,说这个就是基环内向森林啊,然后类似后缀数组一样倍增乱搞一下就能搞出来</del>。但是后缀数组我学得实在垃圾,只会抄板子,有点写不明白,然后我爬了。但是 Luowaterbi 就不一样了,他看了很久的 M,看着看着,Luowaterbi 突然告诉我这个 M 居然只跟每个位置的后继状态数有关。于是我迅速写了一下,<strong>287min1A</strong>,rank 又掉到 46 了,我只能爬。</p>
<p>总成绩是 5 - 605,rank 50/186。只能说是稳定发挥,但是什么时候能进个 Au 线呢……其实这场六题 + 手速就 Au 了,就是说其实还是有希望的吧……(?</p>
<h1 id="Solution(咕咕)"><a href="#Solution(咕咕)" class="headerlink" title="Solution(咕咕)"></a>Solution(咕咕)</h1>
[20200607] 2018-2019 ACM-ICPC, Asia Qingdao Regional Contest
http://tanakarino.cn/2020/06/07/20200607-2018-2019-ACM-ICPC-Asia-Qingdao-Regional-Contest/
2020-06-07T11:24:11.000Z
2020-06-07T12:03:24.647Z
<h1 id="Review"><a href="#Review" class="headerlink" title="Review"></a>Review</h1><p>感觉还是好菜,该加训了……</p>
<p>刚开场就开始演队友。我直接读了 J,迅速大力交了两发 WA 的二分答案。一看 M 过了好多,又大力交了一发 WA。想了一会,才突然意识到 J 题的合法性并不是单调的,于是,Luowaterbi 认为答案就是一个前缀和加一个后缀 min,我照做,又交了一发 WA。</p>
<p>此时已经快一个小时了,而我们两个水题都 WA 着……我突然意识到 M 题需要特判 <code>0 1</code>,改了改过了,<strong>58min2A</strong>。owojiecao 突然发现 J 题 $0$ 必买,应该去掉 $0$ 再做。我和 Luowaterbi 纷纷感叹自己傻逼,然后我手抖写错,又交了两发才过,<strong>70min5A</strong>。此时发现 C 过题人数和 J 差不多,于是读 C,发现是个分类讨论傻逼题,然后我第一发没讨论没 $1$ 的情况,第二发交了个弱智 PE,第三发才过,<strong>84min3A</strong>。</p>
<p>我智商完全不在线,短短不到一个半小时的时间连交了七发罚时,已经同题数垫底 rank 105,感谢队友不杀之恩。</p>
<p>好在中期打得还不算烂。此时大多数人都是三题, DEF 都是刚有几个人通过。我读了 D,Luowaterbi 读了 F,无果,交换题意,我发现 F 是个找规律的构造题,手玩了一会之后会了,但没认真审题又交了一发 PE,<strong>142min2A</strong>,rank 上升到 43<del>,还是同题数垫底</del>。我们又读了难度跟 DF 相近的 E,我说二分答案显然,于是转化成询问给定步数之内能否访问每个位置给定次数。想了一会发现大力贪心似乎可行,但没处理好交了发 WA,遂下机交给 owojiecao 写 D。跟 luowaterbi 一起读了很久 E 的代码,改了三次,终于发现我有个地方写了点很弱智的东西……<strong>228min4A</strong>,rank 掉到 55<del>,还是同题数垫底(虽然之后有人帮我们垫底了)</del>。</p>
<p>接下来只有 owojiecao 的 D 比较可以期待的样子,而我和 Luowaterbi 去读剩下的题里读相对可能比较可做的 L。事实证明 L 是个我们之中并没有人会的生成函数,而 owojiecao 的 D 也没调出来……</p>
<p>最后 rank 80/354,什么时候能进个 Au 线呢……</p>
<h1 id="Solution(咕咕)"><a href="#Solution(咕咕)" class="headerlink" title="Solution(咕咕)"></a>Solution(咕咕)</h1>
2020 CCPC-Wannafly Winter Camp Day 1 H
http://tanakarino.cn/2020/06/02/2020-CCPC-Wannafly-Winter-Camp-Day-1-H/
2020-06-02T14:51:00.000Z
2020-06-02T15:39:15.675Z
<h1 id="Problem-H-最大公约数"><a href="#Problem-H-最大公约数" class="headerlink" title="Problem H. 最大公约数"></a>Problem H. 最大公约数</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给出两个整数 $k,n$ ($1 \leq k \leq n$),求最小的 $y$,使得对于任意 $x \in [1,n]$ 且 $x \neq k$,都满足 $\gcd(x, y) \neq \gcd(k,y)$。如果不存在这样的 $y$,输出$-1$。有 $T$ 组测试数据。</p>
<p>$1 \leq T \leq 50$</p>
<p>$1 \leq k \leq n \leq 500$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>不存在这样的 $y$ 当然是骗你的,因为一定存在……</p>
<p>我在狂演 F 题的时候这题就有一些队伍过了,于是 Luowaterbi 和 owojiecao 就在看,但是没什么结论……我演完 F 之后看了一会<del>样例</del>,猜想答案就是 $k \cdot \prod_{i = 1, i \in p}^{\lfloor \frac{n}{k} \rfloor} i$,虽然不会证明但是我们三个都没想到反例,于是我就交了两发 WA,发现需要高精度,用 Java 重写,过了。</p>
<p><del>抄了一个</del>必要性证明大概是这样的:</p>
<ul>
<li>必须保证 $k|y$。否则就有 $\gcd(k,y) \neq k$,又因为显然 $\gcd(k,y) = \gcd(\gcd(k,y),y)$,就不符合题意了啊。</li>
<li>对于 $[1,\lfloor \frac nk \rfloor]$ 中的每一个质数 $p$,必须保证 $p|\frac yk$。否则就有 $\gcd(pk,y) = k \cdot \gcd(p,y/k) = k =\gcd(k,y)$,就不符合题意了啊。</li>
</ul>
2020 CCPC-Wannafly Winter Camp Day 1 F
http://tanakarino.cn/2020/06/02/2020-CCPC-Wannafly-Winter-Camp-Day-1-F/
2020-06-02T14:19:35.000Z
2020-06-02T14:42:36.376Z
<h1 id="Problem-F-乘法"><a href="#Problem-F-乘法" class="headerlink" title="Problem F. 乘法"></a>Problem F. 乘法</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给两个长度分别为 $n,m$ 的数列 $A, B$ 来表示一个 $n \times m$ 的矩阵 $C$(即 $C_{i,j} = A_i \cdot B_j$)。 给出整数 $K$,你需要求出 $C$ 中第 $K$ 大的数。</p>
<p>$1 \leq n,m \leq 10^5$, $1 \leq K \leq n \times m$</p>
<p>$-10^6 \leq A_i,B_i \leq 10^6$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>$O(n \log m \log (\max C_{i,j} - \min C_{i,j}))$ 的做法显然吧……</p>
<p>我们预先对每一行排好序。对于一个假定的答案 $mid$,我们可以 $O(n)$ 枚举行,对于每一行都 $O(\log m)$ 二分一下计算有多少个数大于 $mid$,就能 $O(n \log m)$ 计算 $mid$ 是第几大。又因为 $mid$ 与其位次是单调的关系,那么考虑二分答案 $mid$,就可以 $O(n \log m \log (\max C_{i,j} - \min C_{i,j}))$ 求 $K$ 大了。</p>
<p>二分这种东西需要注意一下细节,尤其是这题还有负数和 $0$……我开场读的第一题就是这个,一眼就会了,以为有希望抢一血,结果是被 <code>lower_bound</code> 和 <code>upper_bound</code> 演了很久,调了一个小时……太丢人了……</p>
<h2 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h2>
2020 CCPC-Wannafly Winter Camp Day 1 C
http://tanakarino.cn/2020/06/02/2020-CCPC-Wannafly-Winter-Camp-Day-1-C/
2020-06-02T10:58:21.000Z
2020-06-28T12:45:25.227Z
<h1 id="Problem-C-染色图"><a href="#Problem-C-染色图" class="headerlink" title="Problem C. 染色图"></a>Problem C. 染色图</h1><p><del>色图?哪里有色图?</del></p>
<h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>在一张无向图中,如果存在一种方案,使得给每个结点染上一种颜色 $c_i \in [1,k]$ 后,任意一对相邻结点的颜色不同,则称这张无向图可以 $k$ 染色。在有 $n$ 个节点的、可以 $k$ 染色的所有简单图中,选出边数最多的一个,我们记其边数为 $g(n,k)$。</p>
<p>现在,给定 $n,l,r$,求 $\sum_{i=l}^{r} g(n,i)$ 对 $998244353$ 取余后的结果。有 $T$ 组测试数据。</p>
<p>$1 \leq T \leq 1000$</p>
<p>$1 \leq l \leq r \leq n \leq 10^9$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>考虑一张有 $n$ 个结点染上 $k$ 种颜色,每种颜色使用了 $a_i$ 次。既然只有同色是不能连边的,那么我们把除了同色的团只玩的边全部连起来。一个大小为 $x$ 的团有 $\frac{x(x+1)}2$ 条边,那么总边数应该是</p>
<script type="math/tex; mode=display">
\binom{n}{2} -
\sum_{i=1}^{k} \binom{a_i}{2}</script><p>不难发现,要最大化总边数其实也就是要最小化 $\sum_{i=1}^k a_i^2$。为满足这一点,$a_i$ 应当均分。如果 $a_i$ 不是均分,即存在 $i,j$ 使得 $|a_i-a_j| \geq 2$,那么令 $a_i = a_j = \frac{a_i+a_j}{2}$,$\sum_{i=1}^k a_i^2$ 显然变小。所以,$a_i$ 肯定是均分,即有 $n \bmod k$ 个 $a_i$ 等于 $\lfloor \frac nk \rfloor + 1$,剩下的 $k - n \bmod k$ 个 $a_i$ 等于 $\lfloor \frac nk \rfloor$。</p>
2020 CCPC-Wannafly Winter Camp Day 1 B
http://tanakarino.cn/2020/06/02/2020-CCPC-Wannafly-Winter-Camp-Day-1-B/
2020-06-02T10:56:20.000Z
2020-06-02T10:57:57.627Z
<h1 id="Problem-B-密码学"><a href="#Problem-B-密码学" class="headerlink" title="Problem B. 密码学"></a>Problem B. 密码学</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>将小写字母从 $0$ 到 $25$ 编号,将大写字母从 $26$ 到 $51$ 编号。用字符 $a$ 加密字符 $b$ 得到的字符,是 $a$ 和 $b$ 的编号相加后对 $52$ 取余后的结果对应的字符。用字符串 $key$ 加密字符串 $s$ 得到的字符串长度与 $s$ 相同,其中,第 $i$ 个字符是用 $key_i$ 加密 $s_i$ 得到的字符,如果 $key$ 的长度不够,则将 $key$ 重复多次。</p>
<p>有 $n$ 个字符串 $s_1,s_2,\dots,s_n$ 和 $m$ 次加密操作 $(x_1,y_1),(x_2,y_2),\dots,(x_n,y_n)$。第 $i$ 次加密操作用 $s_{x_i}$ 加密 $s_{y_i}$,并将 $s_{y_i}$ 替换为加密结果。现在给出 $n$ 个字符串的最终结果和 $m$ 次加密操作,求 $n$ 个字符串的初始值。</p>
<p>$1 \leq n,m \leq 1000$, $1 \leq x_i,y_i \leq n$</p>
<p>$1 \leq |s_i| \leq 100$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>模拟题,没啥好说的……加密是加解密就是减……</p>
<h2 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">long</span> <span class="keyword">long</span> ll;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> N = <span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"><span class="keyword">int</span> x[N], y[N];</span><br><span class="line"><span class="keyword">char</span> s[N][<span class="number">105</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">chartoint</span> <span class="params">(<span class="keyword">char</span> c)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> ((<span class="string">'a'</span> <= c) && (c <= <span class="string">'z'</span>)) <span class="keyword">return</span> c - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span> ((<span class="string">'A'</span> <= c) && (c <= <span class="string">'Z'</span>)) <span class="keyword">return</span> c - <span class="string">'A'</span> + <span class="number">26</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">char</span> <span class="title">inttochar</span> <span class="params">(<span class="keyword">int</span> a)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> ((<span class="number">0</span> <= a) && (a <= <span class="number">25</span>)) <span class="keyword">return</span> a + <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span> ((<span class="number">26</span> <= a) && (a <= <span class="number">51</span>)) <span class="keyword">return</span> a - <span class="number">26</span> + <span class="string">'A'</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> n, m;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= m;i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &x[i], &y[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%s"</span>, &s[i]);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = m;i >= <span class="number">1</span>;i--) {</span><br><span class="line"> <span class="keyword">int</span> lx = <span class="built_in">strlen</span>(s[x[i]]);</span><br><span class="line"> <span class="keyword">int</span> ly = <span class="built_in">strlen</span>(s[y[i]]);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>;j < ly;j++) {</span><br><span class="line"> <span class="keyword">int</span> tmp = <span class="number">0</span>;</span><br><span class="line"> tmp += chartoint(s[y[i]][j]);</span><br><span class="line"> tmp -= chartoint(s[x[i]][j % lx]);</span><br><span class="line"> tmp += <span class="number">52</span>;</span><br><span class="line"> tmp %= <span class="number">52</span>;</span><br><span class="line"> s[y[i]][j] = inttochar(tmp);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%s\n"</span>, s[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
2020 CCPC-Wannafly Winter Camp Day 1 A
http://tanakarino.cn/2020/06/02/2020-CCPC-Wannafly-Winter-Camp-Day-1-A/
2020-06-02T10:49:10.000Z
2020-06-02T10:51:54.240Z
<h1 id="Problem-A-期望逆序对"><a href="#Problem-A-期望逆序对" class="headerlink" title="Problem A. 期望逆序对"></a>Problem A. 期望逆序对</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给 $n$ 个随机变量 $x_1,x_2,\dots,x_n$,$x_i$ 的值是 $[l_i,r_i]$ 中随机选取的整数。你可以将这些随机变量排成任意的顺序,求逆序对数期望的最小值对 $998244353$ 取余后的结果。</p>
<p>$1 \leq n \leq 5 \times 10^3$, $1 \leq l_i \leq r_i \leq 10^9$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>事实上,取值的期望(即 $\frac{l_i+r_i}{2}$)越小就应该排在越前面,这样得到的序列的逆序对数的期望就是最小的。</p>
<p>为什么呢?对于任意一个序列,我们选择相邻的两项,其他项不动,考虑这两项是否应该交换。如果前一项的期望比后一项大,那么显然交换之后逆序对数减小,所以答案的序列中相邻里两项一定是前一项的期望比较小,而要满足这个性质就只能令期望单增,于是我们确定了这个序列的顺序。</p>
<p>之后就只需要 $O(n^2)$ 枚举每一对变量,$O(1)$ 计算其产生的逆序对数就行了。把两个变量看成分别在 $x$ 轴和 $y$ 轴上的区间,两个变量之间能产生的逆序对数其实就等价于一个矩形在 $y=x$ 的一侧的面积吧,这个就各凭本事吧,现场写的是分类讨论。</p>
<h2 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="keyword">long</span> ll;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> N = <span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> M = <span class="number">1e3</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> mod = <span class="number">998244353</span>;</span><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">qpow</span> <span class="params">(ll a, ll b)</span> </span>{</span><br><span class="line"> ll ret = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (b) {</span><br><span class="line"> <span class="keyword">if</span> (b & <span class="number">1</span>) ret = ret * a % mod;</span><br><span class="line"> a = a * a % mod;</span><br><span class="line"> b >>= <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">inv</span> <span class="params">(ll a)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> qpow(a, mod - <span class="number">2</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">node</span> {</span></span><br><span class="line"> <span class="keyword">int</span> l, r;</span><br><span class="line">} a[N];</span><br><span class="line">ll invv[N];</span><br><span class="line"><span class="keyword">bool</span> <span class="keyword">operator</span> < (<span class="keyword">const</span> node& a, <span class="keyword">const</span> node& b) {</span><br><span class="line"> <span class="keyword">return</span> a.l + a.r < b.l + b.r;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">calc</span> <span class="params">(<span class="keyword">const</span> node& a, <span class="keyword">const</span> node& b)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (a.l <= b.l) {</span><br><span class="line"> <span class="keyword">if</span> (a.r <= b.l) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> ((a.r > b.l) && (a.r <= b.r)) {</span><br><span class="line"> ll tmp = a.r - b.l + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> tmp * (tmp - <span class="number">1</span>) / <span class="number">2</span> % mod;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (a.r > b.r) {</span><br><span class="line"> ll tmp = (b.r - b.l + <span class="number">1</span>);</span><br><span class="line"> ll sum = tmp * (tmp - <span class="number">1</span>) / <span class="number">2</span> % mod;</span><br><span class="line"> sum += (a.r - b.r) * tmp;</span><br><span class="line"> <span class="keyword">return</span> sum % mod;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> ll tmp = (a.r - a.l + <span class="number">1</span>);</span><br><span class="line"> ll sum = tmp * (tmp - <span class="number">1</span>) / <span class="number">2</span> % mod;</span><br><span class="line"> sum += (a.l - b.l) * tmp;</span><br><span class="line"> <span class="keyword">return</span> sum % mod;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> n;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &a[i].l, &a[i].r);</span><br><span class="line"> }</span><br><span class="line"> sort(a + <span class="number">1</span>, a + n + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> invv[i] = inv(a[i].r - a[i].l + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> ll q = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> q *= a[i].r - a[i].l + <span class="number">1</span>;</span><br><span class="line"> q %= mod;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> ll p = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>;j <= n;j++) {</span><br><span class="line"> ll tmp = calc(a[i], a[j]);</span><br><span class="line"> tmp = tmp * invv[i] % mod;</span><br><span class="line"> tmp = tmp * invv[j] % mod;</span><br><span class="line"> p += tmp;</span><br><span class="line"> <span class="keyword">if</span> (p >= mod) p -= mod;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, p);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
[20200426] 2020 Petrozavodsk Winter Camp Day 5
http://tanakarino.cn/2020/06/02/20200426-2020-Petrozavodsk-Winter-Camp-Day-5/
2020-06-02T10:42:17.000Z
2020-06-02T10:54:26.212Z
<h1 id="Review"><a href="#Review" class="headerlink" title="Review"></a>Review</h1><p><a href="https://codeforces.com/profile/triple__a" target="_blank" rel="noopener">triple_a</a> 问我和 <a href="https://codeforces.com/profile/nezzar" target="_blank" rel="noopener">clp012345</a> 要不要来玩,于是我就打了<del>,前 World Finalist 带飞谁不爱呢</del>。</p>
<p>因为纯属娱乐所以可能并不是全力打,不过也并没有做到同一时刻只有一个人写……总之就是图一乐吧。</p>
<p>刚开场的时候因为是娱乐所以他们两个也就随便开题不跟榜了,我们各自读了一下几道题。clp012345 开始猛凹 C 凹了接近两个小时<del>,结果是 C 最后也没过</del>。我看到有人过 L 就大力 WA 了一发,发现把大于写成大于等于,<strong>43min2A</strong>。B 题 triple_a 说只会 TLE 的枚举子集,于是 clp012345 说 Sum over Submask DP 能做,<strong>51min1A</strong>。triple_a 又读了 I 题,说做法显然但是难写,我一看题居然是原题(2016 CCPC Changchun J),可能毛子出题人没看过国内这场,于是直接复制粘贴交了,<strong>71min1A</strong>。G 我之前就说是大力枚举,但我不会计算几何,让 triple_a 写了,<strong>105min2A</strong>。我们交流了一下 F 的题意,然后 triple_a 觉得他大概会写,然后他说反正是随便打打所以他有事要出门了(草)。我大力猜了一下 A 题有个结论,但是需要筛 $10^{11}$ 以内的质数个数,时间复杂度没法接受,clp012345 告诉我有一种叫作 <a href="https://tanakarino.cn/2020/04/27/Meissel-Lehmer算法/">Meissel-Lehmer</a> 的神棍算法可以 $O(n^\frac 23)$ 求这个东西……找了个板子复制粘贴(?),然后我搞错边界,又贡献一发罚时,<strong>156min2A</strong>。期间 clp012345 单切了 H(我题都没读……),<strong>167min2A</strong>。<del>接下来我假装看 C 和 E,其实已经没思路了完全躺了。</del>但他们两个还是很猛,clp012345 单切了 J,<strong>230min4A</strong>。triple_a 回来把 F 写了,<strong>257min2A</strong>。我跟 clp012345 说 E 题的圆其实就是竖线,他说用离散化线段树维护一下就行,<strong>293min4A</strong>。</p>
<p>前 World Finalist 带飞果然牛逼,9 个题<del>,力压 dmy</del>,我全程躺着被带飞。</p>
<h1 id="Solution(待完善)"><a href="#Solution(待完善)" class="headerlink" title="Solution(待完善)"></a>Solution(待完善)</h1><h2 id="Problem-A-Bags-of-Candies"><a href="#Problem-A-Bags-of-Candies" class="headerlink" title="Problem A. Bags of Candies"></a>Problem A. Bags of Candies</h2><p><a href="https://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-A/">https://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-A/</a></p>
<h2 id="Problem-B-Binomial"><a href="#Problem-B-Binomial" class="headerlink" title="Problem B. Binomial"></a>Problem B. Binomial</h2><p><a href="https://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-B/">https://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-B/</a></p>
Meissel-Lehmer算法
http://tanakarino.cn/2020/06/02/Meissel-Lehmer%E7%AE%97%E6%B3%95/
2020-06-02T10:34:41.000Z
2020-06-02T10:38:20.810Z
<h1 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h1><p>首先引入一个问题。LibreOJ 6235:令 $\pi(n)$ 为 $n$ 以内的质数个数,求 $\pi(n)$ $(1 \leq n \leq 10^{11})$。</p>
<p>当然你可能会说你有分段打表的做法。众所周知,$1 \leq l \leq r \leq 10^{12}$ 且 $0 \leq r - l \leq 10^6$ 时,$[l, r]$ 中质数个数有一个很 trivial 的类似 Eratosthenes 筛的 $O((r - l)\log \log \sqrt r)$ 的做法。在这个基础上把 $[1, 10^{11}]$ 分成 $10^4$ 段,每段在本地预处理一下,段外的部分再单独算。这样分段打表确实可以卡过去,但是我们有不那么生草的做法:<del>洲阁筛</del> <del>min_25筛</del> Meissel-Lehmer 算法可以在 $O(n^{\frac23})$ 的时间复杂度内计算 $\pi(n)$。</p>
<p>这个算法在算法竞赛选手之间并不怎么普及(所以想写这篇文章),可能是因为实现起来确实略微有点麻烦(尤其是对不能抄板子的 OI 选手来说?)。虽然说 Miller-Rabin 素性判断和 Pollard-Rho 质因数分解也很麻烦,但也面对的场景大概也多一些,相比之下 Meissel-Lehmer 算法在算法竞赛生涯中可能遇不到几次(?)。目前见到的相关题目只有 2016 ICPC 沈阳赛区网络赛 J 和 2020 毛营 Day5 I,更生草的是可以看到后者的官方题解就是分段打表……大概进一步印证了这个算法的冷门……?</p>
<h1 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h1><p>令 $p_1, p_2, \dots, p_m$ 为前 $m$ 个质数。定义 $\phi(n, m)$ 为 $[1, n]$ 内所有质因子都大于 $p_m$ 的数的个数,$P_k(n, m)$ 为 $[1, n]$ 内恰有 $k$ 个大于 $p_m$ 的质因子的数的个数。 特别地,令 $P_0(n, m) = 1$,则有</p>
<script type="math/tex; mode=display">
\phi(n, m) = P_0(n, m) + P_1(n, m) + \dots + P_k(n, m) + \dots</script><p>注意到 $p_m^k > n$ 时有 $P_k(n, m) = 0$,所以,如果我们取 $x \in [n^{\frac13}, n^{\frac12}]$ 并令 $m = \pi(x)$,对于任意 $k \geq 3$,都有 $P_k(n, m) = 0$。即,</p>
<script type="math/tex; mode=display">
\phi(n, m) = P_0(n, m) + P_1(n, m) + P_2(n, m)</script><p>根据定义,显然 $P_1(n, m) = \pi(n) - m$,于是我们对上式适当变换,得</p>
<script type="math/tex; mode=display">
\pi(n) = \phi(n, m) - P_2(n, m) + m - 1</script><p>接下来,我们只需要计算 $\phi(n, m)$ 和 $P_2(n, m)$。根据定义,不难得到其计算方式如下:</p>
<script type="math/tex; mode=display">
P_2(n, m) = \sum_{x < p \leq \sqrt n} (\pi(\frac np) - \pi(p) + 1)</script><script type="math/tex; mode=display">
\phi(n, m) =
\begin{cases}
[n], & m = 0 \\
\phi(n, m - 1) - \phi(\frac {n}{p_m}, m - 1), & m \geq 1
\end{cases}</script><h1 id="复杂度分析"><a href="#复杂度分析" class="headerlink" title="复杂度分析"></a>复杂度分析</h1>
2020 Petrozavodsk Winter Camp Day 5 L
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-L/
2020-06-02T10:21:19.000Z
2020-06-02T10:23:21.328Z
<h1 id="Problem-L-Wizards-Unite"><a href="#Problem-L-Wizards-Unite" class="headerlink" title="Problem L. Wizards Unite"></a>Problem L. Wizards Unite</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给 $1$ 把金钥匙(可多次使用的钥匙),$k$ 把银钥匙(只能用一次)。给 $n$ 个箱子,每个箱子有一个打开所需时间 $t_i$(跟钥匙类型无关)。一把钥匙同时只能开一个箱子,问打开所有箱子所需的最小总时间。有 $z$ 组测试数据。</p>
<p>$0 \leq k < n \leq 10^5$</p>
<p>$0 \leq t_i \leq 10^9$</p>
<p>$\sum n \leq 10^6$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>本场最简单的题。</p>
<p>不失一般性,我们认为所有箱子按 $t_i$ 排升序。显然方案只能是 $k$ 把银钥匙都用来开一个箱子,金钥匙开其他所有箱子,而答案就是以下两者中的较大值:用银钥匙的箱子中耗时最长的一个的耗时;金钥匙开其他所有箱子的耗时之和。</p>
<p>注意到答案无论如何也不可能小于 $t_n$,也就是说用银钥匙开 $t_n$ 箱子一定不会浪费时间。那么为了令金钥匙耗时之和尽可能小,实际上 $k$ 把银钥匙开的就是最右边的 $k$ 个箱子,于是答案就很显然了。时间复杂度 $O(n \log n)$。</p>
2020 Petrozavodsk Winter Camp Day 5 J
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-J/
2020-06-02T10:14:35.000Z
2020-06-02T10:16:51.608Z
<h1 id="Problem-J-Space-Gophers"><a href="#Problem-J-Space-Gophers" class="headerlink" title="Problem J. Space Gophers"></a>Problem J. Space Gophers</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>有一个由边长为 $1$ 的小正方体组成的边长为 $10^6$ 的实心正方体。在其中挖 $n$ 条隧道,每条隧道用 $(-,y_i,z_i)$ 或 $(x_i,-,z_i)$ 或 $(x_i,y_i,-)$ 表示。挖隧道的含义是,指定其中两个维度的坐标,沿平行于另一个维度轴线的方向把 $10^6$ 个方块拿走。挖完 $n$ 条隧道之后,$q$ 次询问两个点 $(s_x,s_y,s_z)$ 和 $(t_x,t_y,t_z)$ 是否可以通过若干条隧道连通。保证 $s$ 和 $t$ 处于隧道中。有 $z$ 组测试数据。</p>
<p>$1 \leq z \leq 6$</p>
<p>$1 \leq n \leq 3 \times 10^5$, $1 \leq x_i,y_i,z_i \leq 10^6$</p>
<p>$1 \leq q \leq 5 \times 10^5$, $1 \leq s_x,s_y,s_z,t_x,t_y,t_z \leq 10^6$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>clp 单切之前大致跟我讲了一下做法。实际上两条隧道连通 iff 某一个维度坐标相等或相差 1,于是我们要做的事情就是把所有这样的隧道对找出来,在并查集上 merge 起来。</p>
<p>这个东西说起来简单,实现起来就比较呕吐……具体还是看代码吧……<del>似乎是这篇文章里最长的代码</del></p>
<h2 id="Code-By-clp012345"><a href="#Code-By-clp012345" class="headerlink" title="Code (By clp012345)"></a>Code (By clp012345)</h2>
2020 Petrozavodsk Winter Camp Day 5 I
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-I/
2020-06-02T10:11:12.000Z
2020-06-02T10:18:22.867Z
<h1 id="Problem-I-Sum-of-Palindromes"><a href="#Problem-I-Sum-of-Palindromes" class="headerlink" title="Problem I. Sum of Palindromes"></a>Problem I. Sum of Palindromes</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>把给定的 $n$ 位数分解成不超过 $25$ 个回文数(不允许前导零)。有 $z$ 组测试数据。</p>
<p>$1 \leq z \leq 20000$</p>
<p>$1 \leq n \leq 10^5$</p>
<p>$\sum n \leq 3 \times 10^6$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>跟国内比赛撞车了(2016 CCPC Changchun J),可能这些毛子出题人没怎么看国内比赛的题。</p>
<p>做法很简单,就是每次减掉小于当前数的最大的回文数。很显然每次可以减掉一半的长度,所以大概只需要 $\log n$ 次就够了。唯一的难点在于实现有点恶心,需要上高精度,不过我直接复制以前打 16 长春时候的代码了。(那个时候写得很丑不要骂我呜呜呜)</p>
<h2 id="Code-By-Nanako"><a href="#Code-By-Nanako" class="headerlink" title="Code (By Nanako)"></a>Code (By Nanako)</h2>
2020 Petrozavodsk Winter Camp Day 5 H
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-H/
2020-06-02T10:07:10.000Z
2020-06-02T10:18:45.548Z
<h1 id="Problem-H-Lighthouses"><a href="#Problem-H-Lighthouses" class="headerlink" title="Problem H. Lighthouses"></a>Problem H. Lighthouses</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给一个有 $n$ 个顶点的凸多边形,其顶点用 $(x_i,y_i)$ 表示。以 $n$ 个顶点为结点,给定 $m$ 条边 $(u_i,v_i)$。希望求出图上最长的(指欧几里得距离)且不和自己相交的(几何意义上)路的长度。有 $z$ 组测试数据。</p>
<p>$3 \leq n \leq 300$, $0 \leq m \leq \frac{n(n-1)}{2}$, $1 \leq u_i \neq v_i \leq n$</p>
<p>$-10^9 \leq x_i, y_i \leq 10^9$</p>
<p>$\sum n \leq 3000$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>这题赛中我读都没读就被 clp012345 切了,赛后才看。</p>
<p>经过观察我们发现其实合法的路只能是在环上往一个方向转,那么我们上一个区间 DP 就可以了。开三个维度,分别表示起点、终点、顺/逆时针,状态转移 $O(n)$ 枚举。时间复杂度 $O(n^3)$。</p>
<p>区间 DP 要上环的话,通常做法就是开两倍数组复制一遍吧,参考石子合并。</p>
2020 Petrozavodsk Winter Camp Day 5 G
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-G/
2020-06-02T10:04:41.000Z
2020-06-02T10:19:12.918Z
<h1 id="Problem-G-Invited-Speakers"><a href="#Problem-G-Invited-Speakers" class="headerlink" title="Problem G. Invited Speakers"></a>Problem G. Invited Speakers</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给定 $2n$ 个不同的点 $(x_i,y_i)$,$A$ 类型和 $B$ 类型各 $n$ 个,保证不存在三点共线。希望你能给出一种方案把它们配对成 $n$ 对 $AB$,并且每对 $AB$ 之间用折线($[1, 100]$ 条首尾相连的线段)相连,折线之间两两不交。有 $z$ 组测试数据。</p>
<p>$1 \leq z \leq 200$</p>
<p>$1 \leq n \leq 6$</p>
<p>$0 \leq |x_i|,|y_i| \leq 100$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>我读的题,第一反应是:就这?</p>
<p>还害我确认了好几遍题意和数据范围。</p>
<p><del>精通脚撕 FFT 的各种姿势的</del>队友 Luowaterbi 曾经告诉我,没有三点共线的时候,两种一样多的点必然存在一种配对方案使得每对之间只用一条线段相连并且所有线段都不交。既然这题数据范围这么小,直接大力枚举配对方案,再大力枚举判断是否存在两线段交就行了。时间复杂度 $O(n!n^2)$。</p>
2020 Petrozavodsk Winter Camp Day 5 F
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-F/
2020-06-02T09:57:10.000Z
2020-06-02T10:19:42.090Z
<h1 id="Problem-F-The-Halfwitters"><a href="#Problem-F-The-Halfwitters" class="headerlink" title="Problem F. The Halfwitters"></a>Problem F. The Halfwitters</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给定长度 $n$,给定 $a, b, c$,给 $d$ 次询问。每次询问是一个长度为 $n$ 的排列,你可以对这个票列做三种操作:</p>
<ol>
<li><p>花费 $a$ 代价,交换相邻的两个数;</p>
</li>
<li><p>花费 $b$ 代价,翻转这个排列;</p>
</li>
<li><p>花费 $c$ 代价,shuffle 这个排列。</p>
</li>
</ol>
<p>对于每次询问,你需要求出,在最优的操作策略下,把排列排成升序所需的最小期望代价。有 $z$ 组测试数据。</p>
<p>$2 \leq n \leq 16$, $1 \leq a, b, c \leq 1000$, $1 \leq d \leq 10000$</p>
<p> $\sum d \leq 10^5$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>考虑只有第一种操作,我们不难发现,总代价只跟逆序对数 $inv$ 有关。</p>
<script type="math/tex; mode=display">
ans_{1}(inv) = inv \cdot a</script><p>考虑加上第二种操作,我们不难发现,先翻转一下再只进行以上操作可能会更快!</p>
2020 Petrozavodsk Winter Camp Day 5 B
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-B/
2020-06-02T09:51:19.000Z
2020-06-02T10:20:11.602Z
<h1 id="Problem-B-Binomial"><a href="#Problem-B-Binomial" class="headerlink" title="Problem B. Binomial"></a>Problem B. Binomial</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>给定序列 $a_1,a_2,\dots, a_n$,问有多少对 $(a_i,a_j)$ 满足 $\binom{a_i}{a_j} \bmod 2 = 1$ 。有 $z$ 组测试数据。</p>
<p>$1 \leq z \leq 10$</p>
<p>$1 \leq n \leq 10^6$, $1 \leq a_i \leq 10^6$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>Lucas 定理有一个经典的推论:</p>
<script type="math/tex; mode=display">
\binom{a_i}{a_j} \bmod 2 = 1 \leftrightarrow a_i \& a_j = a_j</script><p>因此,问题转化为求</p>
<script type="math/tex; mode=display">
\sum_{i=1}^{n} \sum_{j=1}^{n} [a_i \& a_j = a_j]</script><p>记 $m = \lceil \log (\max a_i) \rceil$。显然,暴力枚举可以做到 $O(n^2)$ 的复杂度。优化一下,枚举子集可以做到 $O(3^m)$ 的复杂度。但是要通过这题还是不够。clp012345 说可以 <a href="https://codeforces.com/blog/entry/45223" target="_blank" rel="noopener">Sum over Submask DP</a> 做到 $O(m2^m)$,于是 triple_a 就现学现用写了一个。</p>
<p>这个算法本身就不讲了,可以看上面链接的文章。在国内,这个算法一般被称作快速莫比乌斯变换 (FMT) 或者子集和变换,英文不好的话也可以搜这两个词,但感觉其实大部分文章都写得对新手不是很友好。个人觉得可以看<a href="http://blog.leanote.com/post/rockdu/TX20" target="_blank" rel="noopener">这篇</a>,我觉得下面这张插图真的把 FMT 解释得非常清楚。</p>
2020 Petrozavodsk Winter Camp Day 5 A
http://tanakarino.cn/2020/06/02/2020-Petrozavodsk-Winter-Camp-Day-5-A/
2020-06-02T09:46:06.000Z
2020-07-20T18:30:07.925Z
<h1 id="Problem-A-Bags-of-Candies"><a href="#Problem-A-Bags-of-Candies" class="headerlink" title="Problem A. Bags of Candies"></a>Problem A. Bags of Candies</h1><h2 id="Statement"><a href="#Statement" class="headerlink" title="Statement"></a>Statement</h2><p>把 $A = {1,2,\dots,n}$ 分成尽可能多对,使得每一对的两个数都不互质,问 $n$ 减去配对次数的值。有 $z$ 组测试数据。</p>
<p>$1 \leq z \leq 5$</p>
<p>$2 \leq n \leq 10^{11}$</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>半场的时候动这个题的队伍只有个位数。可能大家都觉得有别的题可做,不像我这么菜别的都不会就来瞎猜结论了啊。于是结论就是,将 $1$ 和大于 $\lfloor \frac n2 \rfloor$ 的质数从 $A$ 里删掉,剩下的集合 $A’$ 一定是可以匹配满的,所以配对次数就是 $\frac {|A’|}2$。</p>
<p><del>赛中是瞎猜的,</del>这里给一个简单证明。</p>
<p>将 $A’$ 的所有元素按最大质因子 $d$ 分组,那么每组都可以表示成 $A_d = {d,2d,\dots,\lfloor \frac nd \rfloor d}$ 的形式(注意并不一定 $|A_d|=\lfloor \frac nd \rfloor$,比如 $77 \notin A_7$),显然组内的数都是不互质的。</p>
<p>如果 $|A_d|$ 是偶数,直接令组内的数任意两两配对;如果 $|A_d|$ 是奇数,则除了 $2d$ 以外任意两两配对。所有组都作完以上匹配之后,剩下的数都是 $2$ 的倍数,所以也都不互质,也可以任意两两配对。注意到对于任意 $d$ 有 $|A_d| \geq 2$ 即不存在 $|A_d| = 1$,所以最后剩下的数显然至多只有一个。</p>