AtCoder Regular Contest 113
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
- 如果 \(C_a\) 是偶数
重复对两个 a 操作,可以使得 \(S\) = bb..b ( \(C_b\) 个),且不可能把 a 放到末尾,因此答案就是 bb..b .
- 如果 \(C_a\) 是奇数且 \(S\) 结尾是
ab
依然重复操作 a ,可以将 \(S\) 变为 bb..bab 的形式。不删除 b ,也无法移动 a ,所以这就是答案。
- \(C_a\) 为奇数,\(S\) 结尾
abb
重复操作不在结尾的 a ,变成 bb..bab 的形式。同理这个也是最大值。
- \(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\) 出现。 - 对两个不在开头连续
a的a操作,不会让新的满足 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]\) 区间的一个随机实数点上。求两两之间最短距离的期望。
这是什么毒瘤场 /tuu 只有两个场上只写了 F 的老哥过 F 了,所有人都到 E 戛然而止 /jk
话虽如此 ABCD 还是很清新的说……
咕咕咕.

浙公网安备 33010602011771号