这次比赛打得相(can)当(bu)不(ren)错(du),一道题都没有A~
A题忘了数据范围,打了个 O ( n ) O(n) O(n)的上去,居然只T了两个点……
B题经过一番挣扎,乖乖打暴力……35分海星……
C题由于数据太弱,不多说。
题目大意:
已知将数量分别为 a , b a,b a,b的两堆物品 (我会告诉你原题是鸽子!?) 合并成一堆的代价为 a ⊕ b a\oplus b a⊕b,求合并 n n n个物品的最大代价。 n n n个物品可以看成 n n n堆物品,每堆一个。 n ⩽ 2 32 n\leqslant 2^{32} n⩽232。
先给出答案:
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(n−1)2n(n−1)−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<i⩽2nmax{f(i)+f(n−i)+(i⊕(n−i))}打表可以发现 f ( i + 1 ) − f ( i ) = ( i ⊕ 1 ) f(i+1)-f(i)=(i\oplus1) f(i+1)−f(i)=(i⊕1)。
引理: i , j ⩾ 1 i,j\geqslant1 i,j⩾1,则 ( i ⊕ j ) ⩽ i + j (i\oplus j)\leqslant i+j (i⊕j)⩽i+j。
证: ( i ⊕ j ) = ( i ∨ j ) − ( i ∧ j ) (i\oplus j)=(i\lor j)-(i\land j) (i⊕j)=(i∨j)−(i∧j),又 i + j = ( i ∨ j ) + ( i ∧ j ) i+j=(i\lor j)+(i\land j) i+j=(i∨j)+(i∧j),所以 ( i ⊕ j ) ⩽ ( i ∨ j ) ⩽ i + j (i\oplus j)\leqslant(i\lor j)\leqslant i+j (i⊕j)⩽(i∨j)⩽i+j。
当 n ⩽ 4 n\leqslant 4 n⩽4时,可以手动算出结论成立。
当 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(i−1)=i−1±1所以对于任意 2 < i ⩽ n 2 2<i\leqslant \frac n2 2<i⩽2n,
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(i−1)+f(n−i+1)⩾f(i)+f(n−i)+n−i⋅2+1⩾f(i)+f(n−i)又对于任意 1 ⩽ i < n 1\leqslant i<n 1⩽i<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⊕(n−i))(1⊕(n−1))⩽n=1+n−1+(1∧(n−1))⋅2⩾n−2所以对于任意 2 < i ⩽ n 2 2<i\leqslant \frac n2 2<i⩽2n,
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(n−1)+(1⊕(n−1))f(2)+f(n−2)+n−2×2+1+n−2f(2)+f(n−2)+n⋅2−5f(2)+f(n−2)+nf(i)+f(n−i)+(i⊕(n−i))
注意 n ( n − 1 ) n(n-1) n(n−1)可能会爆long long
,要先除后乘。
原题: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 1⩽n⩽105,1⩽m⩽k⩽105。
如果只有操作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] y−a[x]。而且操作1显然只需要选择 y y y最大的一个。
又一个坑点:如果 y − a [ x ] y-a[x] y−a[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值排序。
原题: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 k⩽10。
稍微搞一下就可以发现这个题KMP是做不了的(扩展KMP可以做)。
我们枚举 S 0 S_0 S0的每一个后缀,求出这个后缀与 S S S的最长公共前缀,那么这个公共前缀后面的一个位置就可以成为一个失配的位置。于是可以求 k k k次最长公共前缀,用完 k k k次失配的机会,比较 S 0 S_0 S0中对应子串和 S S S剩余的部分是否相等。求最长公共前缀和比较子串的操作可以用 二希+哈分 二分+哈希。