广二联考题解补全计划:
第十六套
T1:构造
T2:观察性质,DP
T3: bitset 优化DP,状态设计
T4: 平衡树动态维护欧拉序
-
T1:
简单的构造题,发现性质就很简单,自己当时还因为技术问题卡了2个小时,这导致后面时间不够,提升T1做题速度,别被签到卡了 -
T4:
平衡树动态维护欧拉序,之前单独加训过,不管 -
T3:
观察到式子重复性很高
$ f_{i+1,j+1}|=f_{i,j} \ \ \ \ \ \ \ \ \ s_i=t_j$
$ f_{i,j+2}|=f_{i,j} \ \ \ \ \ \ \ \ \ \ \ t_{j+1}=t_{j+2}$
我们考虑这个特殊的配对,枚举j,把 \(f_i\) 塞到bitset里,如果 \(t_{j+1}=t_{j+2}\) 那么把j 的bitset拉过来,提前处理好字符的bitset,就可以了 -
T2:
考虑第一问答案肯定是 \(maxdep\),经过简单证明我们发现能动这个点当且仅当子树外没有深度大于等于他的点。
于是我们可以只操作长链。
于是我们可以处理每个点能操作的时间区间
于是我们设计状态 \(f_{l,r,j}\) 表示l,r这段长链独立出来,l及其祖先操作了j次,转移分开转移,是一个记搜形式,也可以倒着DP
\(f_{l,r,j}=f_{l,r-1,j+1}\)
$f_{l,r,j}=f_{l,p-1,j} \times f_{p,r-1,j+1} \times \binom{r-l}{p-l} $
第十七套:
T1:取模性质,倍增
T2: DP优化,状态优化
T3:容斥原理,数位DP
T4:不会,神秘可持久化平衡树,WBLT
T1:
首先先提一个关于取模的性质,一个数对一个比它小的数取模,大小一定减半,考虑对 $ \frac {n}{2}$ 分治即可。
我们先预处理出来每个数后面第一个比他小的位置,这样形成一个树形结构。
根据前面的性质,有:
\(S_p(x) = \lfloor \dfrac{x}{a_q} \rfloor S_q(a_q-1) + S_q(x \bmod a_q)\),预处理出 \(S_p(a_p-1)\) 就可以做到只处理log次,每次还需要树上倍增找下一个比他小的,那么两只log即可快速查询
T2:
萌熊原题,写一下思考过程:
-
因为只关心英雄集合,我们贪心地让所选英雄集合去对抗尽可能小的
怪兽 -
于是 \(n^{3}\) 式子很好想,我们枚举集合大小 $k $ ,那么设计 \(f_{i,j}\) 枚举到第i个英雄,赢了j场,转移就不写了
-
优化前途在于枚举状态,我们发现我们 \(k\) 是必须要枚举的,前面设计的状态如果我们要求英雄输就很不好处理,我们考虑前后两端枚举,前面枚举赢的集合,后面枚举输的集合,最后再拼起来
-
发现不能直接拼,我们找到这样一个位置 \(a_k < b_p < a_{k+1}\),这样我们发现前面没赢的都能在后面输,后面没输的都能在前面赢。在这个位置拼起来就行了
T3:
UNR好题
之前学容斥有一个式子是 $ x_i \le b_i \ \ \ 求 \sum x_i=m$ 的方案数,那我们容斥做就好了
这个题是小于等于,那我们新加一个盒子,表示在这个盒子里的我们扔掉。
设 $ A=n+m+k(c-1) $,把后面那一坨拆拆,得到一个下降幂形式,把它看做多项式:
拆一下系数,有
下面你要求后面那一坨 \(b^i\) 的和
设计 \(f_{i,j,k}\) 表示第 i 位 目前集合大小为j,\(x^k\)前面的系数:
注意到上面下降幂式子只有在为初始值为正时有意义,数位DP一下顶没顶上界即可
点击查看代码
int Ans=0;
for(int K=0;K<=m;K++) {
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
int A=(Nm+m+K*(c-1)%P)%P;
g[0][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<=m;j++) {
g[i][j]=g[i-1][j]*(A-i+1)%P;
if(j) g[i][j]=(g[i][j]-g[i-1][j-1])%P;
}
vector<int > B=n+m+K*(c-1);
if(B[0]<0) continue;
while(B.size()<=m) B.push_back(0);
int mx=0;
for(int i=m+1;i<B.size();i++) mx=max(mx,B[i]);
if(mx) f[m+1][0][0][0]=1;
else f[m+1][0][0][1]=1;
for(int i=m;i>=1;i--)
for(int j=0;j<=K;j++) {
for(int z=0;z<=m;z++) {
if(B[i]>1) {
f[i][j][z][0]=(f[i+1][j][z][1]+f[i+1][j][z][0])%P;
if(!j) continue;
for(int w=0;w<=z;w++) {
int zy=f[i+1][j-1][w][0]+f[i+1][j-1][w][1],xs=pw[i*(z-w)];
f[i][j][z][0]=(f[i][j][z][0]+C[z][w]*zy%P*xs)%P;
}
}
else if(B[i]==1) {
f[i][j][z][0]=(f[i+1][j][z][1]+f[i+1][j][z][0])%P;
if(!j) continue;
for(int w=0;w<=z;w++) {
int zy=f[i+1][j-1][w][0],xs=pw[i*(z-w)];
f[i][j][z][0]=(f[i][j][z][0]+C[z][w]*zy%P*xs)%P;
zy=f[i+1][j-1][w][1];
f[i][j][z][1]=(f[i][j][z][1]+C[z][w]*zy%P*xs)%P;
}
}
else {
f[i][j][z][0]=f[i+1][j][z][0];
f[i][j][z][1]=f[i+1][j][z][1];
for(int w=0;w<=z;w++) {
int zy=f[i+1][j-1][w][0],xs=pw[i*(z-w)];
f[i][j][z][0]=(f[i][j][z][0]+C[z][w]*zy%P*xs)%P;
}
}
}
}
int res=0;
for(int i=0;i<=m;i++) res=(res+(f[1][K][i][0]+f[1][K][i][1])*g[m][i]%P)%P;
if(K&1) res=-res;
Ans=(Ans+res+P)%P;
}
田安源题目:
T1矩阵乘法板子,T2哈希板子,T3:单调队列优化DP,T4:分块
T3:设计 \(f_i=f_j+1\) ,\(f_i\) 代表这个位置必须选
设 \(L_i\) 表示不包括i的区间l最靠右的位置,因为不能漏区间不选
\(R_i\) 表示包括i 的区间l最靠左的位置,因为不能重复选
特殊处理一下,L取前缀max,R取后缀min,O(n)求一下
单调队列维护即可
有使用数学归纳法不用单调队列的,这里不提
T4: 场切,水题,b 的值域很小,发现 a 也可以取模,那么两个相邻的数贡献的a是一些区间,分块去做就可以

浙公网安备 33010602011771号