AtCoder Regular Contest 113

Contest Link

C 题没开 long long 见了祖宗。

D - Sky Reflector

在一个 \(n\times m\) 的矩阵中填数,每个格子填 \(1\leq x\leq k\) ,设 \(A_i\) 是行最小值,\(B_i\) 是列最大值。求可能的 \((A,B)\) 序列个数。对 \(998244353\) 取模。


如果 \(n=1\) 或者 \(m=1\) ,那么直接就是 \(k^m\) 或者 \(k^n\) .

对于剩下的情况,设 \(A_1\)\(\max\{A_i\}\)\(B_1\)\(\min\{B_i\}\) 。下面构造一种方案,使得满足上述条件,且 \(A_1\leq B_1\)\(A,B\) 序列均可以取到。

放置方案如下:

  • \(A_1,B_1,A_2,B_2\)\((1,1),(2,1),(2,2),(1,2)\)
  • \(A_i,B_i\)\((i,1),(1,i)\)\(i\ge 3\)
  • 其余:对于第 \(i\) 行的元素,令其等于 \(A_i\) .

不难发现这个构造一定是合法的。然后只需要对满足条件的 \(A_1,B_1\) 计数即可。

枚举 \(A_1\) ,设为 \(x\) ,那么 \(A\) 序列的方案数是 \(x^n-(x-1)^n\) ,减去没出现 \(x\) 的情况;\(B\) 序列的方案数是 \((k-x+1)^m\) ,最小值 \(B_1\ge A_1\)

//Author: RingweEH
void bmod( int &x,int y ) { x+=y-Mod; x+=(x<0)*Mod; }
int n,m,k;

int main()
{
	n=read(); m=read(); k=read();
	if ( n==1 ) { printf("%d\n",power(k,m) ); return 0; }
	if ( m==1 ) { printf("%d\n",power(k,n) ); return 0; }
	int ans=0;
	for ( int i=1; i<=k; i++ )
	{
		int t1=power(i,n); bmod( t1,Mod-power(i-1,n) );
		int t2=k-i+1; t2=power(t2,m);
		bmod(ans,1ll*t1*t2%Mod);
	}
	printf("%d\n",ans );

	return 0;
}

E - Rvom and Rsrev

给定一个由 a b 组成的字符串 \(S\) ,求能得到的字典序最大的字符串。每次操作可以:

  • 选择两个 \(S\) 中相同的字符,将这两个字符中间的一段反转,然后删去这两个字符。

字符串总长 \(\leq 2e5\) .


极速爪巴。这分讨太 /tuu 了…… 是我见过最长的AT题解 Official 翻译官已上线。

设定:\(S\)\(C_a\)a\(C_b\)b .

S​ 结尾为 a

\(k\)\(S\) 结尾最长的连续 a 串的起始位置,并令 \(S_0\)b .

通过以下操作可以使 \(S\)\(C_b\)b 全部在开头:

  • 如果存在 \(i\) 使得 \(1\leq i<k\)\(S_{i-1}\) = b\(S_{i}\) = a\(S_{i+1}\) = a ,那么操作 \((i,k)\)\(k\) 前面一个必然是 b
  • 否则,如果存在多个 \(1\leq i<k\) 使得 \(S_{i-1}\) = b\(S_{i}\) = a\(S_{i+1}\) = b , 选择其中任意两个操作(目的是删去 a
  • 否则,如果存在 \(i<k\) 使得 \(S_i\) = a ,操作 \((i,k)\) .
  • 否则结束。

(前两个操作确保 \(S\) 的结尾仍然是 a

为了使得字典序最大,需要找到 \(t_{\max}\) 使得 \(S\) = bb...baa...a\(C_b\)b\(t\)a )。最大化 \(t\) 就是最小化操作次数。下面证明上面的操作最优。

设有 \(x\)a 子串和 \(y\)bb 子串(除了 \(S\) 末尾连续的全 a 串以外)。定义 \(S\) \(\phi(S)\)\(x+2y\) .

那么,不难发现,任意一次对两个 a 的操作使得 \(\phi(S)\) 减少至多 \(2\) ,而希望得到的 \(\phi\)\(0\) ,所以有至少 \(\lceil\phi(S)/2\rceil\) 次操作。上面构造的前两个操作使得 \(\phi\) 每次减少 \(2\) ,第三个操作最多执行一次,因此这种方式达到了这个下界。

S 结尾为 b

  1. 如果 \(C_a\) 是偶数

重复对两个 a 操作,可以使得 \(S\) = bb..b\(C_b\) 个),且不可能把 a 放到末尾,因此答案就是 bb..b .

  1. 如果 \(C_a\) 是奇数且 \(S\) 结尾是 ab

依然重复操作 a ,可以将 \(S\) 变为 bb..bab 的形式。不删除 b ,也无法移动 a ,所以这就是答案。

  1. \(C_a\) 为奇数,\(S\) 结尾 abb

重复操作不在结尾的 a ,变成 bb..bab 的形式。同理这个也是最大值。

  1. \(C_a\) 为奇数,\(S\) 结尾 bbb

如果 \(S\) = aa..abb..b ,答案就是 abb..b

否则,可以通过如下(至多一次)操作将 a 移到 \(S\) 末尾:

  • 如果存在 \(1\leq i\leq |S|-2\) 使得 \(S_i\) = b\(S_{i+1}\) = a\(S_{i+2}\) = a ,操作 \((i,|S|)\) (操作 A )
  • 否则,选择一个 \(1\leq i\leq |S|-2\) 使得 \(S_i\) = b\(S_{i+1}\) = a\(S_{i+2}\) = b ,操作 \((i,|S|)\) (操作 B )

然后 \(S\) 开头就是 \(C_b-2\)b ,显然不可能更大。

现在证明上面的操作最大化了结尾的 a 的个数,同样转化为最小化操作,并定义势。

为了让 a 到末尾,需要操作结尾的 b ,这个操作至多使 \(\phi\) 减少 \(2\) ,且为了保持 b 的个数,这个操作至多一次。所以任何操作至多使得 \(\phi\) 减少 \(2\) ,且我们需要 \(\lceil\phi(S)/2\rceil\) 次操作。

如果存在 \(1\leq i\leq |S|-2\) 使得 \(S_i\) = b\(S_{i+1}\) = a\(S_{i+2}\) = a ,A 操作使得 \(\phi\) 减少 \(2\) 。否则,操作 B 使得 \(\phi\) 减少 \(1\) . 因此,如果 \(\phi\) 初始为奇数,那么我们可以通过上面的操作得到最大值。这种情况下,一共做了 \(\phi/2+1\) 次操作,我们需要证明不可能在 \(\phi(S)/2\) 次操作内完成(这种情况下每个操作都要使得 \(\phi-=2\)

\(S\) 中对 a 的操作如下:

  • \(S\) 开头连续的 a 操作,\(\phi\) 至多减少 \(1\)
  • 对一个开头连续的 a 和一个后面的 a 操作,\(\phi\) 只有在开头连续 a 的个数不大于 \(2\) 的情况下才会减少 \(2\) ,但是这样的操作不会使得新的满足 A 操作的 \(1\leq i\) 出现。
  • 对两个不在开头连续 aa 操作,不会让新的满足 A 操作条件的 \(i\) 出现。

所以 \(\phi/2\) 次操作是不可能的。

//Author: RingweEH
void Task1()
{
	int c1=0,c2=0,c3=0;	//baa,bab,a
	for ( int i=1; i<=n; i++ )
		if ( s[i]=='a' ) c3++;
		else
		{
			if ( c3==1 ) c2++;
			if ( c3>1 ) c1++;
			c3=0;
		}
	int x=c1+(c2+1)/2;
	for ( int i=1; i<=cntb; i++ ) putchar('b');
	for ( int i=1; i<=cnta-2*x; i++ ) putchar('a');
	puts("");
}
void Task2()
{
	for ( int i=1; i<=cntb; i++ ) putchar('b'); puts("");
}
void Task3( int x )
{
	for ( int i=1; i<=cntb-x; i++ ) putchar('b');
	putchar('a');
	for ( int i=1; i<=x; i++ ) putchar('b');
	puts("");
}
void Task4()
{
	int pos=-1;
	for ( int i=1; i<=n-3; i++ ) if ( s[i]=='b' && s[i+1]=='a' && s[i+2]=='a' ) pos=i;
	if ( pos==-1 )
		for ( int i=1; i<=n-3; i++ ) 
			if ( s[i]=='b' && s[i+1]=='a' && s[i+2]=='b' ) { pos=i; break; }
	if ( pos==-1 ) { putchar('a'); for ( int i=1; i<=cntb; i++ ) putchar('b'); puts(""); }
	else 
	{ 
		reverse(s+1+pos,s+n); 
		for ( int i=pos; i<=n-2; i++ ) s[i]=s[i+1]; 
		n-=2; cntb-=2; Task1();
	}
}

int main()
{
	int T; scanf( "%d",&T );
	while ( T-- )
	{
		scanf( "%s",s+1 ); n=strlen(s+1);
		cnta=cntb=0;
		for ( int i=1; i<=n; i++ ) (s[i]=='a') ? cnta++ : cntb++;
		if ( s[n]=='a' ) Task1();
		else if ( cnta%2==0 ) Task2();
		else if ( s[n-1]=='a' ) Task3(1);
		else if ( s[n-2]=='a' ) Task3(2);
		else Task4();
	}

	return 0;
}

F - Social Distance

给定一个长度为 \(n+1\) 的序列 \(X\) ,满足 \(0=X_0<X_1<\cdots<X_N\) .

\(n\) 个人站在数轴上,第 \(i\) 个人的位置在 \([X_{i-1},X_i]\) 区间的一个随机实数点上。求两两之间最短距离的期望。


有翻译了/se 参考题解2

这是什么毒瘤场 /tuu 只有两个场上只写了 F 的老哥过 F 了,所有人都到 E 戛然而止 /jk

话虽如此 ABCD 还是很清新的说……

咕咕咕.
posted @ 2021-03-11 15:15  MontesquieuE  阅读(101)  评论(0编辑  收藏  举报