2022寒假刷题计划(1)
1.28
P4310 绝世好题
二进制小清新dp,\(O(n\log n)\)
CF618F Double Knapsack
神仙构造,大胆猜想,小心求证。
猜想一定存在两段连续的序列满足答案。
前缀和有 \(n+1\) 项,尝试构造值域为 \(n\) 以利用鸽巢定理。
\(suma[i1]-suma[j1]=sumb[i2]-sumb[j2]\) 可以转换为
\(sumb[i2]-suma[i1]=sumb[j2]-suma[j1]\)。
找到第一个大于等于 \(suma[i]\) 的 \(sumb[j]\),此时因为 \(b[j]\in[1,n]\),故 \(sumb[j]-suma[i]\in[0,n)\),值域为 \(n\) ,利用鸽巢定理就可以找到解。
P2371 [国家集训队]墨墨的等式
同余最短路入门题。
同余最短路用来求 \(n\) 个数 \(a_1,a_2\cdots\) 在一定范围内能凑出多少数。
我们任意找一个 \(a_x\) 记为 \(x\)。
把所有自然数按对 \(x\) 取模分为 \(x\) 类。
我们只要找到每一类中第一个能被凑出的数 \(p\),那么该类中后面的数都可以通过 \(p+k\times x\) 凑出来。
考虑如何找到每类中第一个能被凑出的数,建一张有 \(x\) 个点的图,每个点代表每一类数,那么每个点 \(i\) 连一条有向边 \((i,(i+a[j])\bmod x)\),边权为 \(a[j]\),\(j\) 从 \(1\) 到 \(n\),代表从一类数变成另一类数需要加上 \(a[j]\)(此处复杂度 \(O(n x)\))。然后只要从 \(0\) 跑一遍最短路,此时的最短路就代表每类中第一个能被凑出的数了。
然后我们选择 \(x\) 时如果选择最小的 \(x\) 就可以让点数最小,从而降低时间复杂度。
一篇优质博
BZOJ3687 简单题
神仙题bitset不是很会用。。。
因为 \(\sum a\le 2\times 10^6\),所以简单地设 \(dp[i]\) 表示 \(i\) 这个数出现了几次。
对于子集考虑依次添加每个数,就相当于在原本的子集中加上这个数,也就是 \(dp[i+x]=dp[i+x]\bigotimes dp[i]\)。这样是 \(O(n\sum a)\)。由于 dp 是01数组且这一添加操作可以直接看做01串的右移,所以使用bitset优化就可以做到 \(O(\frac{n\sum a}w)\),可以通过本题。
另外,怀疑本题数据有锅,使用快读会在 test2 T掉。
P2473 [SCOI2008] 奖励关
\(1\le n\le 15\) 所以考虑状压dp,设 \(dp[i][j]\) 表示第 \(i\) 轮,状态为 \(j\) 时的期望最大得分。状态数 \(O(2^n k)\)
正推不好想,容易想到倒推,枚举这次的宝物 \(k\),根据 \(j\) 判断能不能选。
如果能选,那么 \(dp[i][j]+=\max(dp[i+1][j|(1<<(k-1))]+p[k],dp[i+1][j])/n\);
如果不能选,那么 \(dp[i][j]+=dp[i+1][j]/n\)。
然后随便d一下就好了。
1.29
P7520 [省选联考 2021 A 卷] 支配
虽然做完了但是感觉不写很快就会忘,所以一定要稍微写一写。
把能够支配一个点 \(i\) 的点叫做点 \(i\) 的支配点。
我们发现一个点的支配点一定呈一条从树根开始的一条链,我们将每个点与链尾(即最近支配点)连边,显然是树形的,也就是支配树。
贴一张 \(O(n^2)\) 建支配树的方法
回到这道题,加边显然只可能让某些点的受支配集(也就是支配点集)变小。
考虑变小的点 \(u\) 和加边 \((x,y)\)。点 \(u\) 支配点集变小意味着一定存在一条路径不经过 \(u\) 的某个支配点也存在一条从 \(1\) 到 \(u\) 的路径(由定义)。且这条路径一定经过\((x,y)\),也就是存在 \(1\rightarrow x\) 和 \(y\rightarrow u\),不经过 \(u\) 的某个支配点(也就是 \(u\) 在支配树上的某个祖先)。我们考虑找到最浅的满足同样条件的 \(u\),那么此时不经过的这个点就是 \(u\) 在支配树上的父亲,此时 \(u\) 的子树都会变。
所以我们的算法就是先考虑 \(y\rightarrow u\),对每个点考虑去掉支配树上的父亲节点后在原图的反图上能走到的点(\(O(n^2)\) 预处理),当这些作为 \(y\) 时 \(u\) 可能有贡献。考虑每个可能有贡献的点 \(u\),只要存在一条不经过 \(u\) 在支配树上父亲的一条 \(1\rightarrow x\) 的路径,\(u\) 及其子树就可以作出贡献。这里的判断也可以 \(O(n^2)\) 预处理。最后再 \(o(n)\) 统计答案就好了。
我写的烂,需要适当卡常。
最后补充一个 DAG 建支配树的方法,就是先求出拓扑序,然后按拓扑序求每个点在支配树上的父亲,就是该点所有入点在已经建出的支配树上的 LCA,所以这样建时间复杂度是 \(O(n\log n)\)。例题。
P7515 [省选联考 2021 A 卷] 矩阵游戏
值域限制下难以构造,考虑先随便构造一个再把它调整到合法状态。
注意到对某一列或某一行交替地加减 \(1\) 不会影响构造,所以我们设某一行交替加减 \(l[i]\),某一列交替加减 \(c[i]\)。
于是有\(0\le a[i][j]\pm l[i]\pm c[j]\le 1\times 10^6\),发现现在的 \(a[i][j]\) 其实已知,于是 \(-a[i][j]\le \pm l[i]\pm c[j]\le 1\times 10^6-a[i][j]\),发现很像差分约束,但是可能会有 \(l\) 和 \(c\) 同号这不符合差分约束的形式。此时我们只要每行交替减加减加和加减加减,每列交替加减加减和减加减加,就可以保证 \(l\) 和 \(c\) 异号了。然后上差分约束板子就可以了。
注意 spfa 判负环时应统计被松弛次数是否大于总点数而不是进队次数。
简单题,感觉比今年noipT1还要简单。
1.30
设 \(f_i\) 表示 \(i\) 结尾时期望有多长的连续 \(o\),\(ans_i\) 表示 \(i\) 结尾时的期望答案。
for(int i=1;i<=n;i++){
if(c[i]=='o')f[i]=f[i-1]+1,ans[i]=ans[i-1]+2*f[i-1]+1;
else if(c[i]=='x')f[i]=0,ans[i]=ans[i-1];
else if(c[i]=='?')f[i]=(f[i-1]+1)/2,ans[i]=ans[i-1]+(2*f[i-1]+1)/2;
}
遇到问号时就是两种都乘上 \(\frac 12\) 相加就好了。
守卫者的挑战
容易设 \(dp[i][j][k]\) 为第 \(i\) 次挑战,已成功 \(j\) 次,当前积累和为 \(k\) 时的成功离开擂台的概率。因为第三维范围很大所以不能搞,但是我们发信其实第三维的有效信息只有 \([-n,n]\) 的范围,因为 \(-1\) 最多只有 \(n\) 个,所以正数也只需要 \(n\) 的大小,所以微调一下就好了。
比较简单的期望dp题,注意空间比较卡,滚动数组到线性空间复杂度。
2.2
一道纯思维题,不涉及什么算法。因为不是很好下手,所以先考虑枚举,枚举 \(a_k\),然后每个数可以对 \(a_k\) 取模,然后得到一个新数组,从这个数组里选两个数再取模最多只会减一个 \(a_k\),所以考虑把所有数分成小于 \(\lfloor \frac{a_k}2\rfloor\) 和大于等于 \(\lfloor \frac{a_k}2\rfloor\) 的数。第一部分怎么加都不会超过 \(a_k\),第二部分怎么加都会超过 \(a_k\)。这样两种有显然的最优解,剩下的就是分别从第一部分和第二部分选,可以对每个数二分找最优解。
这样是 \(o(n^2 \log n)\) 的,所以要做一些优化,首先相同的数只枚举一次,其次从大到小枚举 \(a_k\) 如果答案已经大于等于 \(a_k\) 就可以不用再枚举了。
虽然这两个优化很显然,但可以将复杂度降低,见这篇。
2.3
虽然似乎有找规律然后树上差分一样的神仙做法,但是这道题可以用更套路一点的做法解决。我们考虑知道儿子如何求父亲节点。也就是所有儿子的数加一后合并到一起再加上自己的。
我们用 01-trie 来维护某个节点 val 定义里那些数。因为 01-trie 比较易于处理异或,我们只需要知道每层里 \(1\) 的奇偶性就可以知道异或和了。
于是我们只需要做到 01-trie 合并,01-trie 插入,01-trie 所有数加一。
前两者可以在 \(O(n\log n)\) 和 \(O(\log n)\) 实现。所以注意最后一个操作,要把 01-trie 树维护的数全部加一,我们注意一个数加一就是把末尾一连串 \(1\) 变成 \(0\) 然后把最后一个 \(0\) 变成 \(1\),这在 01-trie 树上可以实现,我们只需要把左右儿子交换就可以实现把最后一个 \(0\) 变成 \(1\),和把一个 \(1\) 变成 \(0\),但只有一个 \(1\),我们需要递归下去把所有 \(1\) 都交换,同时要记住维护每层的 \(1\) 的奇偶性,于是可以这样写:
inline void add(int x,int k,int rt){
num[rt][k+1]+=siz[ch[x][1]]-siz[ch[x][0]];
swap(ch[x][0],ch[x][1]);
if(ch[x][0])add(ch[x][0],k+1,rt);//这里递归的是 ch[x][0] 是因为已经交换了
}
这样的操作是 \(O(\log n)\) 的,但是要注意因为这样操作来实现加一的操作的话,必须要在建树的时候一直把位数建满,这样才可以做到最高位的进位。
另外,要维护的数是距离加 \(v\) 值,所以数的范围是 \(2n\) 级别的。
数论神仙题,仰望神仙赛场推结论。
只需要知道 \(k\times \binom nk =n\times \binom {n-1}{k-1}\) 和二项式定理 \(\sum\limits_{i=0}^n a^i b^{n-i}\binom ni=(a+b)^n\)。
我们可以把多项式拆开,变成 \(\sum\limits_{i=0}^m a_i \sum\limits_{j=0}^n j^ix_j\binom nj\)。然后考虑后面这一坨,我们可以利用上面提到的第一个式子变换 \(j^i\binom nj\)。
当 \(i=0\) 时,可以变成 \(n\),
当 \(i=1\) 时,可以变成 \(n\binom{n-1}{j-1}\),
当 \(i=2\) 时,可以变成 \(n\binom{n-1}{j-1}+(j-1)(n\binom{n-1}{j-1})=n\binom{n-1}{j-1}+n(n-1)\binom{n-2}{j-2}\),
当 \(i=3\) 时,可以变成 \(j(n\binom{n-1}{j-1}+n(n-1)\binom{n-2}{j-2})=(n\binom{n-1}{j-1}+n(n-1)\binom{n-2}{j-2})+(2n(n-1)\binom{n-2}{j-2}+n(n-1)(n-2)\binom{n-3}{j-3})=n\binom{n-1}{j-1}+3n(n-1)\binom{n-2}{j-2}+n(n-1)(n-2)\binom{n-3}{j-3}\)。
我们于是可以发现 \(j^i\binom nj=\sum\limits_{k=1}^i S(i,k)\times n^{\underline{k}}\times\binom{n-k}{j-k}\)。其中 \(n^{\underline{k}}=n(n-1)\cdots (n-k+1)\),即下降幂;\(S(i,k)\) 是前面的系数,根据上面我们推 \(i=3\) 的情形,可以找到 \(S\) 的递推式为 \(S(i,k)=S(i-1,k-1)+i\times S(i-1,k)\),其中 \(S(i-1,k-1)\) 是上一层前一项因乘 \(j\) 而进的,而 \(i\times S(i-1,k)\) 是上一层同一项拆开进位后剩下的。其实这就是第二类斯特林数,不过不知道也没有影响。
然后我们就可以把 \(\sum\limits_{j=0}^n j^ix_j\binom nj\) 变成 \(\sum\limits_{j=0}^n x^j \sum\limits_{k=1}^i S(i,k)\times n^{\underline{k}} \times\binom{n-k}{j-k}\)。
然后我们交换求和号,把和 \(j\) 相关的丢在一起,就是 \(\sum\limits_{k=1}^i S(i,k)\times n^{\underline{k}} \times(\sum\limits_{j=k}^n x^j \binom{n-k}{j-k})\)。
此时发现最后面这坨和 \(j\) 相关的有点像二项式定理,于是尝试地变换,令\(t=j-k,j=t+k\),则 \(\sum\limits_{j=k}^n x^j \binom{n-k}{t-k}=x^k \sum\limits_{t=0}^{n-k}x^t \binom{n-k}{t}=x^k(1+x)^{n-k}\),于是我们就把枚举 \(n\) 变成了 \(n\) 次方。
所以 \(\sum\limits_{j=0}^n j^ix_j\binom nj\) 就可以变成 \(\sum\limits_{k=1}^i S(i,k)\times n^{\underline{k}} \times x^k(1+x)^{n-k}\)
我们经过肉眼观察发现 \(a_0\) 并不适合这个式子,所以把 \(a_0\) 特殊拿出来,最后答案就是 \(a_0(1+x)^n+\sum\limits_{i=1}^m\sum\limits_{j=1}^{i}S(i,j)\times n^{\underline{j}}\times x^j\times (1+x)^{n-j}\),后面三个东西都可以 \(O(m)\) 预处理,\(S\) 可以利用递推式 \(O(m^2)\) 计算,所以总的时间复杂度为 \(O(m^2)\)。
冯巨的神仙做法。
第一次 dfs 维护自己和儿子未使 \(i\) 通电的概率以及 \(i\) 未使父亲通电的概率。
第二次 dfs 维护父亲未使 \(i\) 通电的概率。
注意第二次 dfs 时可能会除以 \(0\) 需要特判一下。