记NKOI NOIP信心赛

说在前面

这次比赛打得相(can)当(bu)不(ren)错(du),一道题都没有A~
A题忘了数据范围,打了个 O ( n ) O(n) O(n)的上去,居然只T了两个点……
B题经过一番挣扎,乖乖打暴力……35分海星……
C题由于数据太弱,不多说。

题目概览

A题

题目大意:
已知将数量分别为 a , b a,b a,b的两堆物品 (我会告诉你原题是鸽子!?) 合并成一堆的代价为 a ⊕ b a\oplus b ab,求合并 n n n个物品的最大代价。 n n n个物品可以看成 n n n堆物品,每堆一个。 n ⩽ 2 32 n\leqslant 2^{32} n232

先给出答案:
a n s = { n ( n − 1 ) 2 if  n  is odd n ( n − 1 ) 2 − 1 if  n  is even ans=\begin{cases} \frac{n(n-1)}2&\text{if $n$ is odd}\\ \frac{n(n-1)}2-1&\text{if $n$ is even} \end{cases} ans={2n(n1)2n(n1)1if n is oddif n is even

出题人ztc.神犇的证明:

设合并 n n n只鸽子的最大时间为 f ( n ) f(n) f(n)
f ( n ) = max ⁡ 1 < i ⩽ n 2 { f ( i ) + f ( n − i ) + ( i ⊕ ( n − i ) ) } f(n)=\max_{1<i\leqslant\frac n2}\{f(i)+f(n-i)+(i\oplus(n-i))\} f(n)=1<i2nmax{f(i)+f(ni)+(i(ni))}

打表可以发现 f ( i + 1 ) − f ( i ) = ( i ⊕ 1 ) f(i+1)-f(i)=(i\oplus1) f(i+1)f(i)=(i1)

引理: i , j ⩾ 1 i,j\geqslant1 i,j1,则 ( i ⊕ j ) ⩽ i + j (i\oplus j)\leqslant i+j (ij)i+j

证: ( i ⊕ j ) = ( i ∨ j ) − ( i ∧ j ) (i\oplus j)=(i\lor j)-(i\land j) (ij)=(ij)(ij),又 i + j = ( i ∨ j ) + ( i ∧ j ) i+j=(i\lor j)+(i\land j) i+j=(ij)+(ij),所以 ( i ⊕ j ) ⩽ ( i ∨ j ) ⩽ i + j (i\oplus j)\leqslant(i\lor j)\leqslant i+j (ij)(ij)i+j

n ⩽ 4 n\leqslant 4 n4时,可以手动算出结论成立。
n > 4 n>4 n>4时,设对任意 k < n k<n k<n,结论成立,则对于任意 2 < i < n 2<i<n 2<i<n
f ( i ) − f ( i − 1 ) = i − 1 ± 1 f(i)-f(i-1)=i-1±1 f(i)f(i1)=i1±1

所以对于任意 2 < i ⩽ n 2 2<i\leqslant \frac n2 2<i2n
f ( i − 1 ) + f ( n − i + 1 ) ⩾ f ( i ) + f ( n − i ) + n − i ⋅ 2 + 1 ⩾ f ( i ) + f ( n − i ) \begin{aligned} f(i-1)+f(n-i+1)&\geqslant f(i)+f(n-i)+n-i\cdot2+1\\ &\geqslant f(i)+f(n-i) \end{aligned} f(i1)+f(ni+1)f(i)+f(ni)+ni2+1f(i)+f(ni)

又对于任意 1 ⩽ i < n 1\leqslant i<n 1i<n
( i ⊕ ( n − i ) ) ⩽ n ( 1 ⊕ ( n − 1 ) ) = 1 + n − 1 + ( 1 ∧ ( n − 1 ) ) ⋅ 2 ⩾ n − 2 \begin{aligned} (i\oplus(n-i))&\leqslant n\\ (1\oplus(n-1))&=1+n-1+(1\land(n-1))\cdot2\\ &\geqslant n-2 \end{aligned} (i(ni))(1(n1))n=1+n1+(1(n1))2n2

所以对于任意 2 < i ⩽ n 2 2<i\leqslant \frac n2 2<i2n

f ( 1 ) + f ( n − 1 ) + ( 1 ⊕ ( n − 1 ) ) ⩾ f ( 2 ) + f ( n − 2 ) + n − 2 × 2 + 1 + n − 2 = f ( 2 ) + f ( n − 2 ) + n ⋅ 2 − 5 ⩾ f ( 2 ) + f ( n − 2 ) + n ⩾ f ( i ) + f ( n − i ) + ( i ⊕ ( n − i ) ) \begin{aligned} &f(1)+f(n-1)+(1\oplus(n-1))\\ \geqslant&f(2)+f(n-2)+n-2\times 2+1+n-2\\ =&f(2)+f(n-2)+n\cdot2-5\\ \geqslant &f(2)+f(n-2)+n\\ \geqslant&f(i)+f(n-i)+(i\oplus(n-i)) \end{aligned} =f(1)+f(n1)+(1(n1))f(2)+f(n2)+n2×2+1+n2f(2)+f(n2)+n25f(2)+f(n2)+nf(i)+f(ni)+(i(ni))

注意 n ( n − 1 ) n(n-1) n(n1)可能会爆long long,要先除后乘。

B题

原题:CF521D
题目大意:
有一个长度为 n n n的数列,第 i i i个数是 A i A_i Ai。现在有 k k k种操作:

  • 1 x y A x A_x Ax变为 y y y
  • 2 x y A x A_x Ax增加 y y y
  • 3 x y A x A_x Ax乘上 y y y

若每种操作只能使用一次, 且一共只能使用 m m m次操作,求一种方案,使得操作完毕后所有数的乘积最大。若相同取操作次数最少的方案,再取字典序最小的方案。
1 ⩽ n ⩽ 1 0 5 , 1 ⩽ m ⩽ k ⩽ 1 0 5 1\leqslant n\leqslant 10^5,1\leqslant m\leqslant k\leqslant 10^5 1n105,1mk105

如果只有操作3,由于最后需要所有数的乘积最大,因此乘法的先后顺序是无关紧要的,直接从大到小排序,选出前面 m m m个就好了。
一个坑点:如果某个乘数没有超过 1 1 1,完全可以不选它,保证操作次数最少。

下面考虑把操作1、2转换成操作3。
先把操作1变成操作2,这个很简单:把 a [ x ] a[x] a[x]变成 y y y就相当于把 a [ x ] a[x] a[x]加上 y − a [ x ] y-a[x] ya[x]。而且操作1显然只需要选择 y y y最大的一个。
又一个坑点:如果 y − a [ x ] y-a[x] ya[x]没有超过 0 0 0,也可以不选它,直接跳过。

这样操作1就没有了。然后把操作2变成操作3。由于要让操作尽可能少,显然有下面两个结论:

  • 先加后乘。
  • 加法从大到小加。

把操作2按 y y y值从大到小排序,把 a [ x ] a[x] a[x]增加 y y y就相当于把 a [ x ] a[x] a[x]乘上 a [ x ] + y a [ x ] \frac{a[x]+y}{a[x]} a[x]a[x]+y,不过此时的 a [ x ] a[x] a[x]已经不是原数列中的数了,而是要算上 y y y之前的加数。 y y y之前的加数肯定要先加上,并且 a [ x ] a[x] a[x]单增, y y y单减, a [ x ] + y a [ x ] \frac{a[x]+y}{a[x]} a[x]a[x]+y也就单减,转换成操作3后 y y y之前的乘数也一定会先乘上。

然后操作2也没有了。

本题要求字典序最小,故最终答案要按操作编号排序。原题要求按操作顺序输出方案,故要按 t y ty ty值排序。

C题

原题:TJOI2017 DNA
题目大意:
给出两个长度不超过 1 0 5 10^5 105的基因序列 S 0 , S S_0,S S0,S,求 S S S S 0 S_0 S0上的匹配次数,最多容忍 k k k次失配。 k ⩽ 10 k\leqslant 10 k10

稍微搞一下就可以发现这个题KMP是做不了的(扩展KMP可以做)。
我们枚举 S 0 S_0 S0的每一个后缀,求出这个后缀与 S S S的最长公共前缀,那么这个公共前缀后面的一个位置就可以成为一个失配的位置。于是可以求 k k k次最长公共前缀,用完 k k k次失配的机会,比较 S 0 S_0 S0中对应子串和 S S S剩余的部分是否相等。求最长公共前缀和比较子串的操作可以用 二希+哈分 二分+哈希。

你可能感兴趣的:(记事库)