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))) ); } } }
有点补不动题,而且期中考试临近,该复习了,有空的话会补题的。