cf Educational Codeforces Round 32

ABC题巨水,D题推导公式后可以快速解决。

没有打实时场,开了一场Virtual。AB题很轻松,然而手速比较慢。

C题其实也很水,可是一直写的很屎,开场11分钟就开了的题,甚至到离结束还有11分钟左右才过,可见码力若的不行。

C题wa太多了,期间get到D的公式,快速通过D题后回头看C,头脑似乎清醒了些,找到了C的错误,才得以AC,可是时间已经不够开后面的题了(虽说开了也不一定会做)。



A. Local Extrema

题意:给定一个长度为n的数组,忽略头尾,定义一个数若比两边都大则称为local maximum,比两边都小则称为local minimum,统称为local extrema。让你求出local extrema的数的总个数。

十分水,存储后处理即可

#include <cstdio>

int main (void){
	
	int n , a[1005] = {} , ans = 0 ;
	scanf ("%d", &n );
	for ( int i = 0 ; i < n ; i ++ ){
		scanf ("%d", &a[i] );
	}
	for ( int i = 1 ; i < n - 1 ; i ++ ){
		if ( ( a[i] > a[i-1] && a[i] > a[i+1] ) || ( a[i] < a[i-1] && a[i] < a[i+1] ) ){
			ans ++ ;
		}
	}
	printf ("%d\n", ans );
	return 0;
}

B. Buggy Robot

题意:有一个机器人,初始位于(0,0)位置,给你一串包含UDLR的字符串,表示它可能的行动,U、D、L、R分别表示向上走(up)、向下走(down)、向左走(left)、向右走(right)一格,要求行动结束后仍位于(0,0)位置,要你输出最大可能的行动次数。

思路:考虑到终点与起点要在同一个点,所以一个U一定对应一个D,一个L一定对应一个R。所以只需记录UDLR各自出现的次数,然后取UD中次数小的那个,加上LR中次数小的那个,即为总的行动对的个数,将行动对个数乘以二即为总的行动次数。


#include <cstdio>
#include <algorithm>

using namespace std;

int main (void){
	
	int n , num[4] = {} ;
	scanf ("%d",&n );
	char str[105] ;
	scanf ("%s", str );
	for ( int i = 0 ; i < n ; i ++ ){
		if ( str[i] == 'L' )	num[0] ++ ;
		if ( str[i] == 'R' )	num[1] ++ ;
		if ( str[i] == 'U' )	num[2] ++ ;
		if ( str[i] == 'D' )	num[3] ++ ;
	}
	
	int ans = ( min ( num[0] , num[1] ) + min ( num[2] , num[3] ) ) * 2 ;
	
	printf ("%d\n", ans );
	
	return 0;
}

C. K-Dominant Character

题意:给你一个字符串s,要求找到一个最小的k,使得对于s的每一个长度为k的子串,都有同一个字符c出现。如样例1:abacaba,输出结果为2:对于每个长度为2的子串,都有字符'a'出现。

思路:其实很简单,输入只包含小写字母,只需要记录每个字符的间隔最大值,然后再取出所有最大值中的最小值即可。维护最大值:在字符第一次出现的时候记录间隔最大值为第一次出现的下标+1,在遍历过一遍串s后,维护最大值为(当前最大值)与(字符最后一次出现到串s结束的长度)之间的最大值。


其实是一道很简单的题,但是头脑不清醒维护条件一直写wa,弱的不行了。


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int main(void){
	
	char str[100005] ;
	int tag[26] , maxn[26] = {} , num[26] = {} ;
	memset ( tag , -1 , sizeof ( tag ) );
	scanf ("%s", str );
	int len = strlen ( str );
	
	for ( int i = 0 ; i < len ; i ++ ){
		if ( tag[str[i]-'a'] == -1 )	maxn[str[i]-'a'] = i + 1 ;
		if ( tag[str[i]-'a'] != -1 ){
			maxn[str[i]-'a'] = max ( i - tag[str[i]-'a'] , maxn[str[i]-'a']);
		}
		tag[str[i]-'a'] = i ;
		num[str[i]-'a'] ++ ;
	}
	
	for ( int i = 0 ; i < 26 ; i ++ ){
		if ( num[i] <= 1 ){
			maxn[i] = 1000000 ;
		}
	}
	
	for ( int i = 0 ; i < 26 ; i ++ ){
		maxn[i] = max ( maxn[i] , len - tag[i] );
	}
	
	int minn = 10000000 ;
	for ( int i = 0 ; i < 26 ; i ++ ){
		if ( tag[i] != -1 && maxn[i] != 0 ){
			minn = min ( minn , maxn[i] );
		}
	}
	
	minn = min ( minn , len / 2 + 1);
	
	printf ("%d\n", minn );
	
	return 0;
}

D. Almost Identity Permutations

题意:给定n和k,n表示一个序列的长度(序列中只包含值为1-n的元素),问你这n个数的排列中有多少个满足:至少有n-k个值满足Pi = i (即处在原来位置)。

以样例1为例:n = 4 , k = 2,问有几个排列满足至少有n-k=2个值处在原来位置,易知答案7的得来:

(1)1 2 3 4   (2)1 2 4 3   (3) 1 4 3 2   (4) 1 3 2 4   (5) 4 2 3 1   (6) 3 2 1 4   (7) 2 1 3 4

思路:k只有1-4四种选择,可以很容易的分析出:

当k=1时,结果为1;

当k=2时,先从n个数中取出n-2个数,表示这n-2个数是处在原位上的,然后a b这两个n-2之外的数交换位置,只有一种情况,所以k=2时,结果为C(n,n-2)*1+1;

当k=3时,同2理,取出n-3个数,剩下3个数(a,b,c)考虑3个数都不在各自位置上的情况,共有两种情况:(b,c,a) 和 (c,a,b),所以k=3时,结果为C(n,n-3)*2+C(n,n-2)*1+1;

当k=4时,同上,取出n-4个数,剩下4个数(a,b,c,d)都不在各自位置上的情况有9种:(b,a,d,c) , (b,c,d,a) , (b,d,a,c) , (c,a,d,b) , (c,d,a,b) , (c,d,b,a) , (d,a,b,c) , (d,c,a,b) , (d,c,b,a),共9种情况,所以k=4时,结果为C(n,n-4)*9+C(n*n-3)*2+C(n,n-2)*1+1。

至于为什么每次都要加上前一个k的结果,是因为要求的是至少有n-k个值满足,当k减小时n-k增大,显然也符合。

由于懒得写组合数,也懒得化简分式,导致第一发wa掉了,于是直接改用java跑大数。


import java.util.Scanner ;
import java.math.* ;

public class Main {
	public static void main ( String[] args ) {
		Scanner in = new Scanner(System.in);
		
		int n = in.nextInt() , k = in.nextInt() ;
		
		in.close();
		
		BigInteger n1 = BigInteger.valueOf(1) ;
		BigInteger n2 = BigInteger.valueOf(n).multiply(BigInteger.valueOf(n-1)).divide(BigInteger.valueOf(2));
		BigInteger n3 = BigInteger.valueOf(n).multiply(BigInteger.valueOf(n-1).multiply(BigInteger.valueOf(n-2))).divide(BigInteger.valueOf(6));
		BigInteger n4 = BigInteger.valueOf(n).multiply(BigInteger.valueOf(n-1).multiply(BigInteger.valueOf(n-2).multiply(BigInteger.valueOf(n-3)))).divide(BigInteger.valueOf(24));
		
		if ( k == 1 ) {
			System.out.println( n1 );
		} else if ( k == 2 ) {
			System.out.println( n1.add(n2) );
		} else if ( k == 3 ) {
			System.out.println( n1.add(n2).add(n3.multiply(BigInteger.valueOf(2))) );
		} else if ( k == 4 ) {
			System.out.println( n1.add(n2).add(n3.multiply(BigInteger.valueOf(2))).add(n4.multiply(BigInteger.valueOf(9))) );
		}
		
	}
}

有点补不动题,而且期中考试临近,该复习了,有空的话会补题的。

猜你喜欢

转载自blog.csdn.net/stupid_turtle/article/details/78504376