Educational Codeforces Round 68 (Rated for Div. 2)



A. Remove a Progression(思维)

原题链接:http://codeforces.com/contest/1194/problem/A


题意: 给你一个数 n,有 1 到 n 的数列,从1开始,每次去掉一个数。首先,去掉第一个,然后从剩下的数中去掉第二个数……,不断去掉,剩下的数必须不少于x,即在剩下的数列中要找的第 x 个数。问第 x 个数是什么。

思路: 可以看出去掉的其实就是原来序列数中的1,3,5…等奇数。那么,我们要求的是剩下数列的第 x 个数,显然就是 2*x。


Code(C++):

#include <iostream>
using namespace std;
int main() {
	int t;	cin>>t;
	while(t--){
		int n,x;
		cin>>n>>x;
		cout<<2*x<<endl;
	}
	return 0;
}


B. Yet Another Crosses Problem(思维)

原题链接:http://codeforces.com/contest/1194/problem/B

题意: 给一张 n * m 的字符地图,问是否存在某个点的行和列所有的单元格均是黑色的,若存在,则输出0,否则输出最少需要涂黑几个单元格才可以实现。

思路: 先记录每行每列所有单元格白色的个数,找出某个点所在行列最少的单元格数,若该点是白色,记得减掉重复的一个白色格子。即输出缺少黑色最少的行列所缺的个数。

注意字符二维数组最好用字符串数组来定义,下标要从0开始


Code(C++):

#include <iostream>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
const int N=5e4+100;
string a[N];
int h[N],l[N];
int main(){
	int t;	cin>>t;
	while(t--){
		memset(h,0,sizeof(h));
		memset(l,0,sizeof(l));
		int n,m;
		cin>>n>>m;
		for(int i=0;i<n;i++)	
			cin>>a[i];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)	//字符串数组下标要从0开始 
				if(a[i][j]=='.')
					h[i]++;
		for(int j=0;j<m;j++)
			for(int i=0;i<n;i++)
				if(a[i][j]=='.')
					l[j]++;
		int k,minn=inf;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(a[i][j]=='.')	//若是白格,要减掉重复的一个 
					k=-1;
				else	//若是黑格,则不需要 
					k=0;
				minn=min(h[i]+l[j]+k,minn);
			}
		}
		cout<<minn<<endl;
	}
	return 0;
}


C. From S To T(思维)

原题链接: http://codeforces.com/contest/1194/problem/C


题意: 三个字符串 s,t,p,问能否将 p 中的字符取出放入 s 中,使 s 成为 t 。

思路:

做法一: 可以运用STL容器中的 map来做,先把 p 字符串的字符存入map容器并计算其个数。然后在 t 字符串中查找 s 字符串相应位置,如果没有相同字符,则在map容器中查看是否有相应字符,若有,则该字符数量减1并将其插入 s 字符串相应位置,若没有,则直接跳出。最后比较操作后的 s 字符串是否与 t 字符串相同,若是,则输出 YES ,否则输出 NO。

做法二: 只需要判断是否满足两个条件:

  1. s 字符串和 p 字符串的所有相应字符数量是否大于等于 t 字符串相应字符数量,如果不够则直接跳出。
  2. 判断s 字符串是否为 p 字符串子序列,即 s 字符串有的字符是否在 t 字符串中均有。

Code1(C++):

#include <iostream>
#include <map> 
using namespace std;
int main(){
	int k;	cin>>k;
	while(k--){
		string s,t,p;
		cin>>s>>t>>p;
		map<char,int> m;
		for(int i=0;i<p.size();i++)
			m[p[i]]++;
		for(int i=0;i<=t.size();i++){
			if(s[i]!=t[i]){
				if(m[t[i]]>0){
					m[t[i]]--;
					s.insert(i,1,t[i]);
				}else
					break;
			}
		}
		if(s==t)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}

Code2(C++):

#include <iostream>
using namespace std;
int main(){
	int q;	cin>>q;
	while(q--){
		string s,t,p;
		cin>>s>>t>>p;
		int lens=s.size();
		int lent=t.size();
		int lenp=p.size();
		int n1[26]={0},n2[26]={0};
		for(int i=0;i<lens;i++)	n1[s[i]-'a']++;
		for(int i=0;i<lenp;i++)	n1[p[i]-'a']++;
		for(int i=0;i<lent;i++)	n2[t[i]-'a']++;
		int vis=1;
		for(int i=0;i<26;i++){
			if(n1[i]<n2[i])
				vis=0;
		}
		int i,j;
		for(i=0,j=0;i<lent;i++){
			if(s[j]==t[i])
				j++;
		}
		if(j!=lens)
			vis=0;
		if(vis)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
}


D. 1-2-K Game(博弈+SG函数+规律)

原题链接: http://codeforces.com/contest/1194/problem/D


题意: 当前在 n 位置,每一次可以向左走1,2,或者 k 步,最左的位置是0,不能走到0的左边, 二人博弈问题,谁没法再走的时候就输掉,问先手必赢还是后手必赢。

思路: 首先确定的是 0 位置是必输位置,而 1 2 和 k 这三个位置可以一步就走到0位置,所以这3个位置是必赢位置,可以递推出sg函数,通过打表来发现规律:

#include <iostream>
using namespace std;
int sg[1010];
int main(){
	int t;	cin>>t;
	while(t--){
		int n,k;
		n=100;
		cin>>k;
		sg[0]=0;
		sg[1]=1;
		sg[2]=1;
		for(int i=3;i<=n;i++){
		    if((i-k)>=0)
		    {
		        if(sg[i-1]==0||sg[i-2]==0||sg[i-k]==0)
		        {
		            sg[i]=1;
		        }
		    }else
		    {
		        if(sg[i-2]==0||sg[i-1]==0)
		        {
		            sg[i]=1;
		        }
		    }
		}
		for(int i=0;i<=n;i++){
			cout<<i<<" "<<sg[i]<<endl; 
		}
	}
	return 0;
}
/*
2
5
0 0
1 1
2 1
3 0
4 1
5 1
6 0
7 1
8 1
9 0
10 1
11 1
12 0
13 1
14 1
15 0
16 1
17 1
18 0
19 1
20 1
21 0
22 1
23 1
24 0
25 1

6
0 0
1 1
2 1
3 0
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 0
13 1
14 1
15 0
16 1
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 0
25 1
*/

通过打表发现:

  1. 如果 k 不是 3 的倍数,那么只要位置是3的倍数就是必输位置,其他位置(除了0)都是必赢位置,所以判断 n 是否为 3 的倍数,若是,则先手必输,即Bob赢,否则,Alice赢。
  2. 如果 k 是 3 的倍数,那么 n 对 k+1 取模,如果取模后其值等于 k ,那么 n 位置必赢,即先手Alice必赢;如果取模后 n 不等于 k ,判断 n 是否为 3 的倍数,若不是,则先手Alice必赢,否则后手Bob必赢。
    这个规律好难发现,看大佬的才知道!

Code(C++):

#include <iostream>
using namespace std;
int main(){
	int t;	cin>>t;
	while(t--){
		int n,k;
		cin>>n>>k;
		if(k%3){
			if(n%3)
				cout<<"Alice"<<endl;
			else
				cout<<"Bob"<<endl;
		}else{
			n%=(k+1);
			if(n==k)
				cout<<"Alice"<<endl;
			else{
				if(n%3)
					cout<<"Alice"<<endl;
				else
					cout<<"Bob"<<endl;
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值