【Codeforces】Educational Codeforces Round 137 - D. Problem with Random Tests

232 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

【Codeforces】Educational Codeforces Round 137 - D. Problem with Random Tests

题目连接

Problem - D - Codeforces

题目大意

给你一个由 nn 个字符组成的字符串 ssss 的每个字符都是 0 或 1。ss 每一位有 12\frac{1}{2} 的概率是 1 ,随机生成。

选择 ss 的任意两个连续子序列(即子串,两个子串可能相交,可能相同,可能不相交)。选择它们后,您计算所选子串对的值,如下所示:

s1s_1 为第一个子串,s2s_2 为第二个子串,将他们视为正整数的二进制表示,如 1101011010 表示 26。最大化 s1s2s_1|s_2,以二进制表示形式打印,不带前导零。

思路

首先为了让答案最大,我们肯定要让串尽可能长,第一个串肯定取 ss 中第一个 11 出现的位置到 nn 所有的字符。此时我们已经确定了 s1s_1,接下来我们求 s2s_2

然后为了最大化解,我们想把 s1s_1 最高位的 0 变成 1。记整个串 ss 中第一个 1 出现的位置是 mm,整个串 ss 里出现 1 之后的第一个 0 的位置是 f0f_0,则第二个串的长度 kk 就是 nf0+1n-f_0+1

枚举 ss 中所有长度为 kk 的第一个数字是 1 的子串,看看和 s1s_1 的或能不能更新答案。易知原串中长度为 kk 的子串数量为 f0mf_0-m,即 ss 中第一个 1 出现后连续出现的 1 的数量。因为 ss 中的 0 或 1 是随机生成的,因此原串中长度为 kk 的子串数量会很少。

代码

#include <bits/stdc++.h>
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=1000001;
int n,m,k;
int a[N],ans[N];
int solve()
{
	scanf("%d",&n);
	m=k=0;
	int f0=0;//第一个串的第一个0 
	for (int i=1;i<=n;++i)
	{
		scanf("%1d",&a[i]);
		if (m==0&&a[i]) m=i;
		if (k==0&&m&&!a[i]) f0=k=i;
		ans[i]=0;
	}
	if (m==0)
	{
		printf("0");
		return 0;
	}
	if (k==0)
	{
		for (int i=1;i<=n;++i) printf("1");
		return 0;
	}
	for (int i=m;i<f0;++i) printf("%d",a[i]);
	k=n-k+1;//k第二个串的长度 
	for (int i=m;i+k-1<=n;++i)//i第二个串的起点 
	{
		if (!a[i]) continue;
		int flag=0;
		for (int j=0;j<k;++j)
		{
			if (flag) ans[j]=(a[i+j]|a[f0+j]);
			if ((a[i+j]|a[f0+j])<ans[j]) break;
			if ((a[i+j]|a[f0+j])>ans[j]) flag=1;
			ans[j]=(a[i+j]|a[f0+j]);
		}
	}
	for (int i=0;i<k;++i) printf("%d",ans[i]);
	printf("\n"); 
}
int main()
{
	solve();
	return 0;
}