0%

思路讲解

处理这种任意组合问题怎么搞?不可能把每个组合都求一遍时,应该怎么办那?

哈哈,其实那就要跳脱出这个组合啦。

看了提示,用异或字典树做。

这是因为字典树共享前缀(假设位数高的为前缀)。

AC代码

https://codeforces.com/contest/2093/submission/315036163

心路历程(WA,TLE,MLE……)

CE

这里的val值最好不要事先写上去,反正codeforces的编译器初始化空间大概是33MB左右,太小了。所以这种结构体可以不赋值。

1
2
3
4
struct Trie{
int val=INF /* ,digit=0 */ ,nxt0=0,nxt1=0;
// bool tag01=false; // tag01好像没有用,但也懒得删了,就当是方便调试
}tr[MAXN*14];

思路讲解

非常明显的二分答案,最小的最大

AC代码

https://codeforces.com/contest/2093/submission/314861882

心路历程(WA,TLE,MLE……)

思路讲解

其实这个题面应该是一个很经典的类似于莫顿编码的东西。

当然,和莫顿编码还是稍微有点区别

image

思路就是针对每个询问递归的找就行了。

AC代码

https://codeforces.com/contest/2093/my

心路历程(WA,TLE,MLE……)

思路讲解

参考以下题解:

https://www.luogu.com.cn/article/z6wql8q2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FOR(i,1,N){cin>>P[i];}
FOR(i,0,N){ // 抽到第i张卡,有多大的概率抽到j张稀有卡
FOR(j,0,N){
if(i>0 && j>0){
// 这第i张没出货 第i张出货了
dp[i][j]=dp[i-1][j]*(1.0-P[i]/100.0)+dp[i-1][j-1]*(P[i]/100.0);
}else if(j==0 && i>0){
dp[i][j]=dp[i-1][j]*(1.0-P[i]/100.0);
}else if(i==0 && j==0){
dp[i][j]=1.0;
}else{ // 剩下的抽0张卡,获得>0张卡的概率自然是0
dp[i][j]=0;
}
}
}

前面这个求抽到第 i 张卡,有多大的概率恰好抽到 j 张稀有卡,还是不难的。

但是这道题目要求的是抽到至少 X 张卡的数学期望,这个的转移有点难,也有点难想。

expi=1+j=0Nexpmax(0,ij)×dp[N][j]exp_i=1+\displaystyle\sum_{j=0}^{N}exp_{max(0,i-j)}\times dp[N][j]

( $ exp_i$ 代表抽到至少 i 张的期望包数,dp[N][j]dp[N][j] 代表该包抽到恰好 j 张稀有卡的概率 )

这个式子初看很难理解,其实细看之下,还是不那么难理解的,1是我这次抽,所以 +1+1,但是我们是要转移的,需要从别的情况转移过来,那从哪些情况那?其实就是从 j=0Nexpmax(0,ij)\displaystyle\sum_{j=0}^{N}exp_{max(0,i-j)} 这些情况转移过来,但是这些转移是有概率的,多大的概率那?dp[N][j]dp[N][j]

当然因为左右两边都包含 expiexp_i 其实我们还要进行一个移项。

expi=1+expi×dp[N][0]+j=1Nexpmax(0,ij)×dp[N][j]expi(1dp[N][0])=1+j=1Nexpmax(0,ij)×dp[N][j]expi=(1+j=1Nexpmax(0,ij)×dp[N][j]) / (1dp[N][0])exp_i=1+exp_i\times dp[N][0]+\displaystyle\sum_{j=1}^{N}exp_{max(0,i-j)}\times dp[N][j]\\ exp_i(1-dp[N][0])=1+\displaystyle\sum_{j=1}^{N}exp_{max(0,i-j)}\times dp[N][j]\\ exp_i=(1+\displaystyle\sum_{j=1}^{N}exp_{max(0,i-j)}\times dp[N][j])\ /\ (1-dp[N][0])

你可能会说,我还是不理解这个 +1+1,或者为什么不是直接用 X/每包的期望稀有卡数量X/每包的期望稀有卡数量。那么我问你,这个得到至少一张稀有卡的期望可能小于 1 吗?不可能吧,因为不可能一包卡都不开就拿到了一张稀有卡吧?所以其实这个 +1+1 就是这里的转移必须要用开卡包来转移。

AC代码

https://atcoder.jp/contests/abc382/submissions/65982174

心路历程(WA,TLE,MLE……)

思路讲解

1
2
3
4
// 首先,上面的块是不会影响下面的块,只有下面的块影响上面的块的份
// 思路其实也不复杂,就是看在这个块下面的块中最高的在哪里。
// 相当于一个range最小值查询,需要用线段树区间修改

AC代码

https://atcoder.jp/contests/abc382/submissions/64644331

心路历程(WA,TLE,MLE……)