zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 113

    Contest Link

    C 题没开 long long 见了祖宗。

    D - Sky Reflector

    在一个 (n imes m) 的矩阵中填数,每个格子填 (1leq xleq 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_1leq 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))(ige 3)
    • 其余:对于第 (i) 行的元素,令其等于 (A_i) .

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

    枚举 (A_1) ,设为 (x) ,那么 (A) 序列的方案数是 (x^n-(x-1)^n) ,减去没出现 (x) 的情况;(B) 序列的方案数是 ((k-x+1)^m) ,最小值 (B_1ge 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
    ",power(k,m) ); return 0; }
    	if ( m==1 ) { printf("%d
    ",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
    ",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) 使得 (1leq i<k)(S_{i-1}) = b(S_{i}) = a(S_{i+1}) = a ,那么操作 ((i,k))(k) 前面一个必然是 b
    • 否则,如果存在多个 (1leq 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) ,所以有至少 (lceilphi(S)/2 ceil) 次操作。上面构造的前两个操作使得 (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) 末尾:

    • 如果存在 (1leq ileq |S|-2) 使得 (S_i) = b(S_{i+1}) = a(S_{i+2}) = a ,操作 ((i,|S|)) (操作 A )
    • 否则,选择一个 (1leq ileq |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) ,且我们需要 (lceilphi(S)/2 ceil) 次操作。

    如果存在 (1leq ileq |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 操作的 (1leq 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 还是很清新的说……

    咕咕咕.
    
    天光渐亮。
  • 相关阅读:
    Java静态方法中使用注入类
    Java FTP辅助类
    Java SFTP辅助类
    MyBatis学习总结——批量查询
    MyBatis学习总结—实现关联表查询
    Redis集群搭建与简单使用
    SQL管理工具
    MySQL锁机制
    MySQL权限管理
    yii框架下使用redis
  • 原文地址:https://www.cnblogs.com/UntitledCpp/p/14518141.html
Copyright © 2011-2022 走看看