补题报告之S班暑训第五场

成绩

image

比赛经过

\(\text{A}\) 题,想了想答案的范围,思路基本上就出来了(但是莫名其妙地挂了 \(10\) 分)。用时估计是 \(20\) 分钟左右。

\(\text{B}\) 题,扫了一眼,由于我把它看成仙人掌了,导致没有去想正解,树和基环树的分还是很好骗的,时间估计是 \(40\) 分钟左右。

\(\text{C}\) 题,看到 \(k\) 次方,我的直觉是用第二类斯特林数转化为下降幂的形式,看看能不能推出式子进行整体递推,然后完美避开了正解的思路,式子推不出来后,二维前缀和跑路,用时不可估计(推反演后的式子耗费极大时间,以至于完全没注意到 \(m \le n\)

\(\text{D}\) 题,打了 \(20\) 分暴力,然后挂没了,呵呵。

赛后补题+分析

\(\text{A}\) gcd

简要/形式化题意

求序列区间互不相同的 \(\gcd\) 的数量。

题解

考虑维护集合 \(Gcd_i\) 表示以 \(i\) 为右端点的区间 \(\gcd\) 集合。那么就有递推式子。

\(Gcd_i=\{a_i\}\bigcup \gcd(Gcd_{i-1},a_i)\)

这里 \(\gcd\) 是作用于整个集合上的生成集合。

如果记 \(ans=\bigcup\limits_{i=1}^{n} Gcd_i\),那么答案就是 \(|ans|\)

如果暴力模拟这个东西它的时间复杂度是多少呢?打死也就 \(O(nV\log V)\),妥妥的过。
(于是考场我脑残写 \(\text{vector}\) 挂了呵呵)

AC code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N];
set<int>Gcd[N],ans;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) {
		Gcd[i].insert(a[i]);
		for(set<int>::iterator it=Gcd[i-1].begin();it!=Gcd[i-1].end();it++) Gcd[i].insert(__gcd(*it,a[i]));
	}
	for(int i=1;i<=n;i++) 
		for(set<int>::iterator it=Gcd[i].begin();it!=Gcd[i].end();it++) ans.insert(*it);
	cout<<ans.size();
	return 0;
}

\(\text{B}\) NP-hard

简要/形式化题意

给定一个点至多属于一个环的无向连通图,求最大独立集。

题解

对于这个给定的图,在 \(\text{dfs}\) 树上,原图上的环会被拆分成一个深度递增的树链和一条由底到顶的返祖边。我们玩一种很新的 \(\text{dp}\)。记 \(dp_{u,0/1,0/1}\) 表示 \(u\) 这个结点选/不选,他所在环深度最大的点选/不选,以 \(u\) 结点为根在 \(\text{dfs}\) 树上的子树所对应的点集在原图中的最大独立集。那么就可以按照常规思路做树形 \(\text{dp}\)

AC code

先咕着。

\(\text{C}\) matrix

简要/形式化题意

求矩阵的所有子矩阵的和的 \(k\) 次方的和。注意 \(n \le m \le n \times m \le 1.1e5\)

题解

对于 \(m=1\) 的情况,前缀和差的 \(k\) 次方用二项式定理展开后,和式交换一下,就可以用后缀和优化做到 \(O(nk)\)。由题可知。\(m \le 331\),枚举 \(y_1,y_2\) 通过贡献的方式转化为 \(m=1\) 的形式,时间复杂度 \(O(knm^2)=O(ks\sqrt s)\),其中 \(s=1.1e5\)

AC code

先咕着。

\(\text{D}\) interval

简要/形式化题意

支持单点修改,区间查询长度为 \(k\) 的互质子区间的数量,其中互质子区间为两两互质的区间。

题解

\(b_x\) 为包含质因数 \(x\) 的单增下标序列。

对于 \(b_x\) 中的相邻两个数 \((x,y)\),则 \([y-k+1,x]\) 的左端点所对应的长度为 \(k\) 的区间不是互质区间。

加入一个原数组的数时,意味着隔开来了两个原来是在 \(b_x\) 中相邻的两个数,可以转化为区间的加减法。

修改原数组中的数,相当于删去一个数再加上一个数。也是区间的加减法。可以用线段树来维护这个过程,也就是查询区间内 \(0\) 的个数(这时候 \(0\) 代表以该位置为左端点的区间是互质区间)。由于维护的新序列恒为非负数,所以其实是要维护最小值的个数,这个东西很好维护。

AC code

先咕着。

考后反思

主要的失误在 \(T3\),想复杂了(可能是因为我市提高组的模拟赛真的出现过第二类斯特林数转下降幂的题,而且都是 \(k\) 次方)。其实 \(m=1\) 的以我的正常水平发挥是有很大概率想出来的。同时还要确保好正解的得分率(仔细观察了一下考场写的 \(T1\) 发现有个地方想错了,导致这是一份错误的代码,能得 \(90\) 说明这数据不够厉害,其实是可以做到爆 0 的)。

最后一个是关于对拍,我发现实际比赛我从没用过这个技巧,以后要养成习惯。

结尾

\(whk\) 多少有点占我时间呀?我怎么没时间补题勒?

posted @ 2023-08-15 21:13  2021hych  阅读(36)  评论(0)    收藏  举报