CF Educational68

本文解析了四道编程挑战题目,包括移除等差数列元素、填充十字架问题、字符串转换验证以及1-2-k游戏的胜负判断。通过算法和数据结构的应用,详细阐述了解题思路和代码实现。
  • A - Remove a Progression
#include <cstdio>
 
int main(){
	int t , n , x ; 
	scanf ("%d",&t) ;
	while(t --){
		scanf ("%d%d",&n,&x) ;
		printf ("%d\n",2*x) ;
	}
	return 0 ; 
}
  • B.Yet Another Crosses Problem

题意:给一个图填充黑色,求填充最少的格子数使得有一个横跨图的十字架,
题解:一开始我是统计每行和每列的黑格子个数,求其最大值和最小值,若是行最大黑格子个数等于n且列最大黑格子个数等于m就存在一个横跨的十字架不需要补充黑色,然后要补充多少用(m+n-a-b)a,b为最大值,但是我发现了bug,就是下面这个两个图,如果按上面那条表达式求第二个图是没有问题的,关键是第一个图,因为行和列要填充的是同一个格子,所以如果按上面的表达式会多算一个格子。
改正:同样还是统计行和列的黑格子个数,然后图要存起来(这里数据太大不能用char二维数组,可以用vector数组存放),然后在后面遍历时,若当前格子为黑格子即‘*’时 ans = min(ans , m+n-row[i]-col[j]) , 若是当前格子为白格子即‘.’ ans = min(ans,m+n-row[i],col[j]) ;
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <vector>
#include <cstring>
using namespace std ; 
const int N = 5e4 + 5 ; 
int row[N] , col[N] ; 
vector<char> v[N] ; 
int main(){
	int t ;
	cin >> t ; 
	while(t --){
		int n , m ; 
		char ch ; 
		cin >> n >> m ; 
		memset(row,0,sizeof(row)) ;
		memset(col,0,sizeof(col)) ; 
		memset(v,0,sizeof(v)) ;
		for (int i = 0 ; i < n ; ++ i){
			for (int j = 0 ; j < m ; ++ j){
				cin >> ch ; 
				v[i].push_back(ch) ;
				if (ch == '*'){
					++ row[i] ; 
					++ col[j] ; 
				}
			}
		}
		int ans = 1e9 ; 
		for (int i = 0 ; i < n ; ++ i){
			for (int j = 0 ; j < m ; ++ j){
				if (v[i][j] == '*'){
					if (ans > m+n-row[i]-col[j])
						ans = m+n-row[i]-col[j] ;
				}
				else{
					if (ans > m+n-row[i]-col[j]-1)
						ans = m+n-row[i]-col[j]-1 ;
				}
			}
		}
		printf ("%d\n",ans) ; 
	}
	return 0 ; 
}

  • C - From S To T
    题意:给出三个字符串s , t , p ,从p中取出字符和s能否组成t
    题解:先处理字符串p,用一个数组记录字符串p中每个字符出现的次数,然后遍历字符串t,用两个变量i,j标记校对到哪里,若是p中的字符不够了则不能组成t,其他详细的见代码。
#include <iostream>
#include <cstring>
using namespace std ;
int alp[30] ; 
int main(){
	int t ; 
	cin >> t ;
	while(t --){
		string s , t , p ; 
		cin >> s ;
		cin >> t ;
		cin >> p ; 
		memset(alp,0,sizeof(alp)) ;
		for (int i = 0 ; i < p.length() ; ++ i)
			++ alp[p[i]-'a'] ;
		int j = 0 , tlen = t.length() ; 
		int i = 0 , slen = s.length() ; 
		bool flag = true ; 
		while(j < tlen){
			if (s[i] == t[j])	++i, ++ j ;
			else if (i >= slen || s[i] != t[j]){
				if (alp[t[j] - 'a'] <= 0)	{
					printf ("NO\n") ;
					flag = false ; 
					break ; 
				}
				else	{
					alp[t[j]-'a'] -- ;
					++ j ; 
				}
			}	
		}
		if (flag){
			if (i == slen && j == tlen) 
				printf ("YES\n") ; 
			else 
				printf ("NO\n") ;
		}
	
	}
	return 0 ; 
}

D. 1-2-K Game(博弈)
题意:给出n个格子和k,可以走1步或者2步或者k步,谁先走到0谁赢,Alice先手,打印出赢的人的名字。
题解:根据题意可知1 2 k 为必赢点,然后推一下规律
比较详细的题解:题解
博弈论:https://www.cnblogs.com/DWVictor/p/10237506.html

#include <cstdio>
int main(){
	int t ;
	scanf ("%d",&t) ; 
	while(t--){
		int n , k ; 
		scanf ("%d%d",&n,&k) ;
		if (k % 3 == 0){
			n %= k+1 ; 
			if (n == k)
				printf ("Alice\n") ;
			else{
				if (n % 3 == 0)		printf ("Bob\n") ;
				else	printf ("Alice\n") ;
			}
			continue ; 
		}
		if (n % 3 == 0)
			printf ("Bob\n") ;
		else
			printf ("Alice\n") ;  
	}
	return 0 ; 
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值