2022年三月好题收集
收集一些有启发的题目
题意:有一个抽奖,$n$种奖品,每种奖品出现的概率为$w_i$,求$k$次抽奖恰好抽到$m$种不同奖品的概率吗,取模 ($n,m,k\leq 50)$
很容易想到阶段就是目前已经抽的次数和目前抽出的不同礼物数
假设抽到的可重集是$S$。
为了方便计算,我们钦定这个排列的编号是单调递增的,我们只需要求出每种排列,再乘上这种排列的全排列个数。
全排列的个数为
$\frac {k!}{cnt_1!\times cnt_2!\dots \times cnt_m!}$
那么答案就为
$\frac {k!}{cnt_1!\times cnt_2!\dots \times cnt_m!} \times p_1^{cnt_1}\times p_2^{cnt_2} \times \dots \times p_k^{cnt_k} $
发现下边那一坨最后计算不好处理,也不好放进状态里,所以考虑把它的代价放到转移里。
$f(i,j,t)$表示前$j$次抽奖(结果均在$[1,i]$)抽出了$k$ 个礼物的概率除以所有次数的阶乘之积。
然后就有转移$$ f(i,j,k) = f(i-1,j,k) +\sum _{t=1} ^j f(i-1,j-t,k-1) \times p_i^{t} \ / t! $$
答案即$f(n,k,m) \times m!$
将不好计算的代价处理到造成它的步骤上
解法2 :
考虑$f(i,j,k)$直接表示前$i$种奖励,抽了j次,有k个不同的概率。
$f(i,j,k) = f(i-1,j,k) + \sum _{t=1} ^ j f(i-1,j-t,k-1) \times p_i ^t \times \binom{j}{t}$
其中组合数表示在t次中选择j次(类似插板)
考虑按单增的顺序考虑集合
题意:给出一个$n \times m$的棋盘,求在上面放$w$个白车,$b$个黑车,黑白车不能互相攻击的方案数。
$(n,m\leq 50 , w ,b \leq 2500)$
很显然地,每行每列要么只放一种车,要么什么都不放。
枚举哪些行哪些列放黑车,白车,这样黑白车都独立了,
$f(i,j,k)$表示在$i$行,$j$列中放置$k$个车的方案数(其中每行、每列至少放置一个车)。
则$ans = \sum _{i=0} ^{n} \sum_{j=0}^m\sum _{x=0} ^{n-i} \sum_{y=0}^{m-j} f(i,j,w) \times f(x,y,h)$
则$f(i,j,k) = \sum _{x=0} ^{i} \sum_{y=0}^j (-1)^{x+y} \text C_{(i-x) * (j-y)}^k * \text C_i^x * \text C_j^y$ 容斥一下即可(钦定哪些行,列不放)
预处理必要的信息,将子问题独立
题意懒得写。
神仙题 %%%
涉及到区间求和的情况一般都考虑前缀和,又因为只有两次“转弯”,设其位置分别为$i$,$j$
则$ans(i,j)$表示在$i$从1下到2,在$j$从2下到3的答案,可以求出
$ans(i,j) = sum1(1\to i) + sum2(i\to j) + sum3(j\to n) - cost$
$ = sum1(i) + sum2(j) - sum2(i-1) + sum3(n) + sum2(j) - sum3(j-1) + cost$
取出与$i,j$分别有关项
令$f(i) = sum1(i) - sum2(i-1) $ , $g(i) = sum2(j) - sum3(j-1)$
则$ans(i,j) = f(i) + g(j) + sum3(n) - cost(i\to j) (i\leq j)$
不好处理的地方在于走下来,如果没有这个“下来”的过程就比较好处理。
观察接下来将代价拆成两部分:从$(1,1) \to (2,j)$的代价以及之后的代价
因为走下来一定需要一条线段,所以我们考虑从哪一条线段走下来的。
从该线段中一点走下来,要么是从之前的某一条线段的末端点走到这个点的,要么是在该线段内第一行走下来的。
令$dp(j)$表示从$(1,1)\to(2,j)$的最优的$f(i) + cost(i\to j)$。
容易发现在这样的枚举下需要用到的只有线段末尾的$dp$值。
$dp(i) =\max _{r_p = i}\{ \max_{j=l_p-1} ^{r_p-1} \{ dp(j) \} ,\max_{j=l_p} ^{r_p} \{f(j)\}\} $
用一个简单的线段树维护$\min\{dp(i-1) , s(i)\}$即可。
接下来需要求出选择每一个线段走下来的价值。
要么直接从该线段上方的某一个点走下来,要么从之前的某一个满足$r_q\leq l_p$的线段走来,则答案为$\max[i,j\in[l_p r_p] ,i\leq j ]\{\max\{dp(i-1) ,f(i)\} , + g(j) \} - cost$
使用线段树分治维护$x(a) + y(b) (a\leq b) $的板子维护即可。
将代价转化为具体与什么相关
题意懒求得写。
考虑起点确定的情况
那么选择路径的代价就是所有点的儿子的代价之和
$f(i,j)$表示从根节点向点i走,目前丢了j个磁铁的最大价值
显然地:
$f(i,j) = max\{f(fa , j) , f(fa,j-1) + sum(i) - a(fa) \}$
其中$sum(i)$表示点i周围的点的价值之和。
话说这么智障一个dp+随机化能骗80分/kk
考虑不确定起点的情况
像点分治一样,考虑将一条路径拆成(可以为空的)两部分。
令这条路径上的最高点为$A$
那么拆成$u \to A , A\to v$两部分。
考虑分别计算两部分的代价。
$up(i,j,1/0)$表示从点$i$的子树向上走到$i$的最大价值。
$down(i,j,1/0)$表示从点$i$向下走到$i$的子树的最大价值。
最后一位表示点$i$是否选择。
发现$down$ 不好转移,会算重,于是参考$70$分dp做法,钦定只算儿子的代价,最后再加上父亲的代价。
于是有转移
$up(i,j,1) = max\{(up(son , j-1 , 1 ) , up(son,j-1,0)\} + sum(i) - a(son)$
$down(i,j,1) = max\{(down(son , j-1 , 1 ) , down(son,j-1,0)\} + sum(i) - a(fa)$
计算答案和许多此类dp一样,都是在合并儿子时计算。
$ans = max_{i+j \leq v}\{ans , max\{up(x,i,1) ,up(x,i,0)\} +max\{down(son,j,1),down(son,j,0)\}\}$
$ans = max_{i+j \leq v}\{ans , max\{up(son,i,1) ,up(son,i,0)\} +max\{down(x,j,1) + a(fa) - a(son) ,down(x,j,0)\}\}$
加上$father$是因为$x$本身的代价是没有计算$father$的
减去$son$是因为$up$计算了$x$本身的代价,然而$son$是路径上更靠前的节点,故不能提供代价。
类似题目 : P3565
类似点分治,考虑将路径分为两部分考虑,采取“儿子向父亲合并”的办法统计答案
题意:已知区间$[l,r]$ , 序列$\{a_i \} = [l,r]$,对所有$a_i$异或上$x$序列变为$\{b_i\}$,给出$\{b_i\} , [ l , r ]$ 求$x$.
$l,r,x< 2^{17} $
妙题
由于是由原序列异或得来的,所以必存在一个$b_i = l \oplus x$ (这个性质似乎可以发扬人类智慧)
那么枚举$x = b_i \oplus l$
考虑对于$x $,如何快速检查。
由于性质$"a \neq b \to a\oplus x\neq b\oplus x"$
所以这些数之间肯定是不同的,所以我们只用考虑$(b_i\oplus x)_{max}$和$(b_i\oplus x)_{min}$是否恰好对应$l,r$即可,因为这样$a_i$对应异或回去恰好是$[l,r]$中的每一个数。
使用Trie即可。
人类智慧法:
由于前面的性质,必然存在一个$b_i = l\oplus x, l+1\oplus x , \dots r\oplus x$
所以$x$必然是某个$b_i \oplus [l,r]$
直接随机取10个$[l,r]$个数,将他们对$\{b_i\}$的异或取交集后 $\text{brute force}$即可。
题意: 维护序列 , 支持以下操作 :
1.区间加上一个数
2.查询区间异或和的后m位(二进制下)
$n,q\leq 10^5 ,m\leq 10$
首先异或和加之间是没有直接性质的(考虑过每一位开一棵线段树,发现不行,因为进位) ,所以难以使用普通的ds维护,因为知道区间异或时整体加是不能 $O(1)$ 地求出的。
对于普通的ds难以维护的题目,考虑分块,却发现分块也卡在了整体打tag的一步上,即无法整体 $O(1)$ 地维护区间异或和随加法的改变量。
由于查询是异或的后10位,于是我们大可不必考虑前面的位,即操作是在模 $2^m$ 的意义下进行的 。
那么此时模意义下数的种类就只有 $2^{10} = 1024$ 种了。
基于元素考虑不现实,考虑基于统计的算法。
有与异或偶数次等于没有异或,所以本质就是查询出现的奇偶性。
加法导致无法按位考虑,所以直接的想法是暴力开1024个桶,统计每个数出现的奇偶性。
然后加就是将桶“旋转”,如下:
假设在模意义下 $+x$ 。
原本在 $0$ 的值会到达 $x$ ,$k$ 会到达 $(k + x) \mod n$ 。
(我甚至去想了splay)
然后发现由于奇偶性是 bool 的,于是直接使用 bitset<1024> 维护!
具体做法就是开一棵线段树,每一个点存一个 bitset 。
区间加时若整个区间被包含,则直接打标记,更改这个点的 bitset 的值,使用位运算优化后 “旋转操作如下” :
s = ( (s << d) | (s >> 1024 - d) ) ;
bitset 左移、右移 多出的位会自动补0 , 很好理解。
区间查询相同,在线段树上把大区间分成很多个小区间,将代表着这些区间的 bitset 异或起来即可得到整个区间出现次数的奇偶性,遍历该 bitset 即可。
时间复杂度 :
$O((n+q) \log n \times \frac a w + q a)$
其中 $ a = 1024$ 。
前半部分是线段树的复杂度计算方式本身复杂度乘上 push_up/down 的复杂度即可。
后半部分是遍历 bitset 的复杂度。
代码较长,放在此处比较占版面,放出关键代码 (线段树) 。
跑的比指令集慢多了
题意: 有一个长为 $n$ 的01序列, 取$k$个子段 , 使得其长度和为 $m$ ,且这些子段的 0总数/1总数 = 原串的 0总数/1总数 。
构造方案使得$k_{min}$ 或输出无解。
神仙题,正常人绝对不会往这个方向想。
首先先判无解,当0,1的数量整除 化简后的 $n/m$ 时一定是有解的,因为只选单个的0、1是可行的。
只用考虑1的个数正确( $= one / n * m$ )即可。
考虑当$n = km$ 时 , 一定有解$k = 1$
证明:
$1\degree $ $k = 1$ 原串即为答案
$2\degree $ $k > 1$
令从i开头长度为m的串的1的个数为$c_i$,即需要找到$c_x = cnt$
那么一定存在$p_1$使得$c_{p_1}\leq cnt$,也存在$p2$ 使得 $c_{p_2}\leq cnt$。
证明是反证,若不存在,则$c_1 + c_{m+1} + \dots c_{n-m+1} <n$
矛盾。
因为$|c_x - c_{x+1}|\leq1$
又因介值定理,一定存在一个$x$使得$c_x = cnt$
当$ n \neq km$ 时,再循环意义下重复刚刚的证明2,即将原串复制若干遍,同样存在$p_1$使得$c_{p_1}\leq cnt$,也存在$p2$ 使得 $c_{p_2}\leq cnt$。
由于现在在循环意义下,所以 $k = 1$ 或 $2$ , 因为有可能是从某个串开头取一段,结尾取一段。
本文已经结束了。本文作者:ღꦿ࿐(DeepSea),转载请注明原文链接:https://www.cnblogs.com/Dreamerkk/p/17970969,谢谢你的阅读或转载!

浙公网安备 33010602011771号