2024.8.1

怎么都 \(8\) 月了。。

\(90+100+40+0\)\(\text{T4}\) 本来有个输出大样例的 \(20\) 分,但被波波制裁取消了、、

T1 集合(mex)

题意:从 \(0 \sim n-1\) 的集合中随机抽出 \(k\) 个数,求这 \(k\) 个数的期望 \(\text{mex}\),答案对 \(998244353\) 取模。

\(\text{T1}\) 做的最快的一集。对于不考虑元素顺序的方案,可以使元素单调不降:这就是之前题的经验(如 \(7.29\) 的 "合并r")。考虑贡献,一个数 \(i\) 有贡献当且仅当 \(\forall j \in [0,i-1]\) 都在序列中,且 \(i\) 不在。那么贡献概率就可知了,便可以这样计算答案期望。

\[ans = \sum_{i=1}^{ \min(n-1,k)}i\cdot\frac{C_{n-i-1}^{k-i}}{C_{n}^{k}} \]

\(i\) 有贡献说明前 \(i\) 位必须是 \(0 \sim i-1\),唯一。所以我们只需考虑后 \(k-i\) 位的选法即可。

还有细节,\(i\) 能不能取 \(k\)?想想 \(i=k\) 有贡献即前 \(k\) 位放满 \(0 \sim k-1\),没有位置放 \(k\) 了,但此时的 \(\text{mex}\) 恰为 \(k\),情况数为 \(1\)

为什么 \(90\) 分?考虑 \(n=k\) 的情况,那就是所有数放满,方案唯一,答案期望为 \(n+1\)。但是按上面的式子,\(C_{n-i-1}^{k-i} = C_{n-i-1}^{n-i}=0\),就错了。

T2 取模

题意:给出 \(n,m\),对于长为 \(n\) 的序列 \(a\),有 \(\forall a_i \in [1,m]\),求所有的

\[\sum_{i=1}^{n-1}\sum_{j=i+1}^n\lfloor \frac{a_i+a_j}{2} \rfloor \]

答案对 \(998244353\) 取模,\(n,m\le10^6\)

前俩都是数学题,这个可以按照前天的 \(\text{T3}\) 大力拆式子,也可以考虑累计贡献,还可以按照奇偶性算。

第一种做法:累计贡献

考虑两个位置 \((a,b)\),设其贡献为 \(x_{a,b}\),剩下 \(n-2\) 个位置随便放,显然有:

\[x_{a,b} = m^{n-2}\sum_{i=1}^{m}\sum_{j=i+1}^{m}\lfloor\frac{i+j}{2}\rfloor \]

发现这样的二元组一共有 \(\frac{n(n-1)}{2}\) 个。

\[ans = \frac{n(n-1)}{2}m^{n-2}\sum_{i=1}^{m}\sum_{j=i+1}^{m}\lfloor\frac{i+j}{2}\rfloor \]

然后怎么搞呢,枚举 \(i,j\)\(O(m^2)\) 了,不好。

有一个很神仙的思路,直接枚举 \(i+j\),再算 \(i\)\(j\) 的可能情况。\(i+j \in [2,2m]\),复杂度 \(O(m)\)

现在我们要解决的问题就是从 \(i+j\) 的和反推 \(i,j\) 种类,其实不太好搞。可以想到的是

  • \(i+j \in [2,m+1]\) 时,\(i\)\(j\) 可以取到 \([1,m]\) 中的任意值,情况数是 \(i+j-1\)
  • 而当 \(i+j \in [m+1,2m]\) 时,并不是随便两个 \(i,j\) 就能凑出来这样的 \(i+j\) 了,怎么计算?考虑找到上界:令 \(a=m\)\(b=i+j-m\);下界:\(a=i+j-m\)\(b=m\),这中间有 \(|(i+j-m)-(m)|+1 = 2m-(i+j)+1\) 种,那么这就是情况数了。

\[ans = \frac{n(n-1)}{2}m^{n-2}( \sum_{i=2}^{m+1}\lfloor\frac{i}{2}\rfloor(i-1) + \sum_{i=m+2}^{2m}\lfloor\frac{i}{2}\rfloor(2m-i+1)) \]

然后就可以 \(O(m)\) 求了。

但是机房巨佬把它化简成了 \(O(\log n)\)……

\[\color{red}ans=\frac{m^nn(n-1)(2m+1)+[m\bmod 2=1]m^{n-2}n(n-1)}{8} \]

第二种做法:大力爆拆

没啥好说的。

求:

\[\sum_{\forall 1\le k\le n,1\le a_k\le m} \sum_{i=1}^{n-1}\sum_{j=i+1}^n \lfloor \frac{a_i+a_j}{2}\rfloor\]

记答案为 \(f_n\),拆递推式。

\[\begin{aligned} f(x)=&\sum_{\forall 1\le k\le x,1\le a_k\le m} \sum_{i=1}^{x-1}\sum_{j=i+1}^x \lfloor \frac{a_i+a_j}{2}\rfloor\\ =&\sum_{\forall 1\le k\le x,1\le a_k\le m} \sum_{i=1}^{x-1}(\sum_{j=i+1}^{x-1}\lfloor \frac{a_i+a_j}{2}\rfloor+\lfloor\frac{a_i+a_x}2 \rfloor)\\ =&\sum_{\forall 1\le k\le x,1\le a_k\le m}(\sum_{i=1}^{x-1}\sum_{j=i+1}^{x-1}\lfloor\frac{a_i+a_j}{2}\rfloor+\sum_{i=1}^{x-1}\lfloor\frac{a_i+a_x}2 \rfloor)\\ =&\sum_{\forall 1\le k\le x,1\le a_k\le m}(\sum_{i=1}^{x-2}\sum_{j=i+1}^{x-1}\lfloor\frac{a_i+a_j}{2}\rfloor+\sum_{i=1}^{x-2}\lfloor\frac{a_i+a_x}2 \rfloor+\lfloor\frac{a_{x-1}+a_x}2\rfloor)\\ =&\sum_{\forall 1\le k\le x,1\le a_k\le m}\sum_{i=1}^{x-2}\sum_{j=i+1}^{x-1}\lfloor\frac{a_i+a_j}{2}\rfloor+ \sum_{\forall 1\le k\le x,1\le a_k\le m} \sum_{i=1}^{x-2}\lfloor\frac{a_i+a_x}2\rfloor +\sum_{\forall 1\le k\le x,1\le a_k\le m} \lfloor\frac{a_{x-1}+a_x}2\rfloor\\ =&m\sum_{\forall 1\le k\le x-1,1\le a_k\le m} \sum_{i=1}^{x-2}\sum_{j=i+1}^{x-1} \lfloor\frac{a_i+a_j}{2}\rfloor+m \sum_{\forall 1\le k\le x-2\cup k=x,1\le a_k\le m} \sum_{i=1}^{x-2}\lfloor\frac{a_i+a_x}2\rfloor +m^{x-2}\sum_{\forall x-1\le k\le x,1\le a_k\le m}\lfloor\frac{a_{x-1}+a_x}2\rfloor\\ =&mf(x-1)+m\sum_{\forall 1\le k\le x-2\cup k=x,1\le a_k\le m} \sum_{i=1}^{x-2}\lfloor\frac{a_i+a_x}2\rfloor+ m^{x-2}\sum_{i=1}^m\sum_{j=1}^m\lfloor \frac{i+j}2\rfloor \end{aligned} \]

中间那项不好搞,设:

\[g(s)=\sum_{\forall 1\le k\le s\cup k=x,1\le a_k\le m} \sum_{i=1}^s\lfloor\frac{a_i+a_x}2\rfloor \]

\[\begin{aligned}g(s)=&\sum_{\forall 1\le k\le s\cup k=x,1\le a_k\le m} \sum_{i=1}^s\lfloor\frac{a_i+a_x}2\rfloor\\ =&\sum_{\forall 1\le k\le s\cup k=x,1\le a_k\le m} (\sum_{i=1}^{s-1}\lfloor\frac{a_i+a_x}2\rfloor +\lfloor\frac{a_s+a_x}2\rfloor)\\ =&\sum_{\forall 1\le k\le s\cup k=x,1\le a_k\le m} \sum_{i=1}^{s-1}\lfloor\frac{a_i+a_x}2\rfloor+ \sum_{\forall 1\le k\le s\cup k=x,1\le a_k\le m} \lfloor\frac{a_s+a_x}2\rfloor\\=&m \sum_{\forall 1\le k\le s-1\cup k=x,1\le a_k\le m} \sum_{i=1}^{s-1}\lfloor\frac{a_i+a_x}2\rfloor+ m^{s-1}\sum_{\forall k=s\cup k=x,1\le a_k\le m} \lfloor\frac{a_s+a_x}2\rfloor\\=& mg(s-1)+m^{s-1} \sum_{i=1}^m \sum_{j=1}^m \lfloor\frac{i+j}2\rfloor \end{aligned} \]

\(g(0) = 0\),那 \(f(2)= g(1) = \displaystyle\sum_{i=1}^m \sum_{j=1}^m \lfloor\frac{i+j}2\rfloor\),这玩意 \(O(m)\) 预处理扫一遍累答案,后面 \(O(n)\) 递推。

第三种做法:奇偶性

\(ans1 = \displaystyle\sum_{i=1}^{n-1} \sum_{j=i+1}^{n}a_i+a_j\),就可以算出来 \(\frac{ans1}{2}\) 记为初始答案,但是有偏差。因为每当奇偶性相同的两数放在一起,最终对答案是无额外影响的:因为是偶数,即不会被下取整砍掉一些答案。但当奇偶性不同的 \(a_i,a_j\) 加起来时,和就会多一个奇数。而每两个奇数就会比单独向下取整多贡献一个 \(1\),那答案就会多 \(1\)。记 \(ans2\) 为奇偶性不同的 \(a_i,a_j\) 对个数,所以最终答案是 \(ans = \frac{ans1}{2}-\frac{ans2}{2}=\frac{ans1-ans2}{2}\)

  • \(ans1\) 的计算

序列一共有 \(m^n\) 种形态,每一个序列有 \(n\) 个位置,每一个位置上的数会被计算 \(n-1\) 次贡献。相当于所有 \([1,m]\) 的数一共会被算 \(m^n\cdot n(n-1)\) 次,每个数等价,那么每个数都被计算 \(\frac{m^n\cdot n(n-1)}{m}\) 次,考虑答案 \(\sum_{i=1}^{m} \frac{m^n\cdot n(n-1)}{m}\),其实就是 \(\frac{m(m+1)}{2}\frac{m^n\cdot n(n-1)}{m}\)

\[ans1 = \frac{m^{n}n(m+1)(n-1)}{2} \]

  • \(ans2\) 的计算

一共 \(n\) 个位置,枚举放偶数的位置个数为 \(i\),放奇数的位置就有 \(n-i\) 个,就有\(i(n-i)\) 个对。这 \(i\) 个位置 \(C_{n}^{i}\) 种放法,设 \(cnt1\)\([1,m]\) 里奇数个数,\(cnt2\) 为偶数。每一个偶数位置都有 \(cnt2\) 个数能放,\({cnt2}^{i}\),奇数位置同理。

\[ans2 = C_{n}^{i}\cdot{cnt2}^{i}\cdot {cnt1}^{n-i}\cdot i(n-i) \]

T3 魔法

考虑用 \(vis_{i,j}\) 表示点 \(i\) 能否到达点 \(j\)。由于空间限制,使用 bitset。预处理时从点 \(i\) 暴力向两边去扫直到遇到比 \(a_i\) 大的点。
可以发现:

  1. 任意两个魔力值相同的点所能到达的点是相同的
  2. 如果一个点能到达一个点 \(i\),那么与 \(a_i\) 值相同的点它都能到达。

于是我们按照魔力值分类,统计每个值能到达哪些点。
我们在扫的时候也能进行优化。我们扫到魔力值相同的点时直接 break(因为那个值在遍历时会继续往后扫);每扫到一个比它小的点就累加上;扫到刚好比它小 \(1\) 的点,累加后直接 break(比它小 \(1\) 的点必然会包含所有比它小的点的信息,该走的都走过了)。
这个复杂度上界是 \((\frac{n^2}{w})\),但跑的很快。

当然还有 \(\text{XiaoLe\_MC3}\) 的线段树优化简图+ Tarjan 缩点 + DAG_dfs 的做法,复杂度瓶颈也是 bitset

T4 排位

考虑转移降星保护卡的数量。易得

\(ans=(B+1+num_{降星保护卡})-(n-B)\)

\(dp[i][j][k]\)表示前\(i\)局,胜了\(j\)局,当前局为胜(\(k=1\))或败(\(k=0\))

  • 对于\(0\)操作,有

\[dp[i][j][0]=max\{dp[i-1][j][0],dp[i-1][j][1]\} \]

  • 对于\(1\)操作,有

\[dp[i][j][1]=max\{dp[i-1][j-1][0],dp[i-1][j-1][1]\} \]

  • 对当前操作,如果前\(d\)局连胜,那么

\[dp[i][j][1]=max\{dp[i-d][j-d][0]+1,dp[i-d][j-d][1]+1\} \]

  • 对于\(?\)操作,只需将上方\(0\)\(1\)的情况全部转移即可

连胜情况可以直接预处理

最后考虑一点小特判

  1. 如果降星保护卡数大于败局数,那么只能使用较小者的数量 (其实如果你不判也能AC)
  2. 如果最后一局胜利且\(ans\)刚好是\(m\)的倍数,那么需要升段
  3. \(ans \le 0\),那么需要输出1(题目要求)

时间复杂度\(O(nB)\)

cin>>d>>B;
    cin>>s;
	n=s.length();
	memset(dp,-0x3f,sizeof(dp));
	dp[0][0][0]=dp[0][0][1]=0;
	int ls=0;
	for(int i=1;i<=n;i++){
		if(s[i-1]=='0') ls=0;
		else{
			ls++;
			if(ls>=d)  combo[i]=true;
		}
	}
	for(int i=1;i<=n;i++){
		int minn=min(i,B);
		for(int j=0;j<=minn;j++){
			if(s[i-1]=='0'){
				dp[i][j][0]=max({dp[i][j][0],dp[i-1][j][0],dp[i-1][j][1]});
			}
			else if(s[i-1]=='1'){
				if(j>=1) dp[i][j][1]=max({dp[i][j][1],dp[i-1][j-1][0],dp[i-1][j-1][1]});
				if(j>=d&&i>=d&&combo[i]) dp[i][j][1]=max({dp[i][j][1],dp[i-d][j-d][0]+1,dp[i-d][j-d][1]+1});
			}
			else /*if(s[i-1]=='?')*/ { 
				dp[i][j][0]=max({dp[i][j][0],dp[i-1][j][0],dp[i-1][j][1]});
				if(j>=1) dp[i][j][1]=max({dp[i][j][1],dp[i-1][j-1][0],dp[i-1][j-1][1]});
				if(j>=d&&i>=d&&combo[i]) dp[i][j][1]=max({dp[i][j][1],dp[i-d][j-d][0]+1,dp[i-d][j-d][1]+1});
			}
		}
	}
	int maxn=max(dp[n][B][0],dp[n][B][1]);
	maxn=min(maxn,n-B);
	int ans=B*2-n+maxn+1;
    if(ans<=0){cout<<1;return 0;}
	if(dp[n][B][0]<dp[n][B][1]&&ans%m==0)ans=ans/m;
	else ans=ans/m+1;

	cout<<ans<<"\n";
	return 0;
posted @ 2024-09-14 21:21  WanGMiNgWeI  阅读(3)  评论(0编辑  收藏  举报