BCSP-X编程样题答案

在开始前,先说明一下,第四题的评测点因BCSP-X官方,无法AC,见谅!!!

1.中彩票

今天是个好日子,小明和小红想买个彩票试一下自己的手气。他们买的彩票是这样兑奖的,只要买到的彩票号码中包含长度大于等于 2 的回文数就判定中奖了。现在请你编写一个程序帮小明和小红检查一下他们是否中奖。
提示:回文数指的是从左向右读和从右向左读都是一样的整数。例如 22 是长度为 2 的回文
数,654456 是长度为 6 的回文数。

共三行。
第一行为一个整数 n,代表小明和小红买到的彩票号码长度。
第二行为小明买到的彩票号码。
第三行为小红买到的彩票号码。

只有一个单词。若两人均中奖,输出“All”;若小明中奖,输出“Ming”;若小红中奖,输出“Hong”;若两人均未中奖,则输出“No”。

对于 60% 的数据,保证输入的 n≤10000,且彩票号码符合特殊性质 1。
对于 100% 的数据,保证输入的 n≤1000000,数据点 7−8符合特殊性质 2,数据的 9−10无特殊性质。

特殊性质解释
特殊性质 1:彩票号码只有两种情况,要么自己本身是一个回文数,要么不包含回文数。
特殊性质 2:彩票号码若包含回文数,则回文数一定在正中间。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
string a,b;
bool hui(string s)
{
	for(int i=0;i<s.size();i++)
	{
		if(s[i]==s[i+1]||i<=n-3&s[i]==s[i+2])
		{
			return 1;
		}
	}
	return 0;
}
int main()
{
	cin >> n;
	cin >> a >> b;
	bool x=hui(a),y=hui(b);
	if(x&&y) cout << "All";
	else if(x&&!y) cout << "Ming";
	else if((!x)&&y) cout << "Hong";
	else cout << "No";
	return 0;
}

2.数字游戏

小明和小红在做一个数字游戏。小明写出一个二进制数,小红必须交换其中的两个数字来得出一个新的二进制数(必须进行交换操作且只能交换两个数字)。小明想知道所有得到的新二进制数中第二大的数是几。小红知道怎么计算最大的数,但是她不知道怎么计算第二大的数,你能帮帮她么?

输入共一行。为小明给出的一个二进制数,不包含前导零。保证所有输入的二进制数通过交换一定能产生至少两个比原数更大的数字。

输出共一行。为小红执行交换操作后第二大的二进制数。

对于 30%的数据,保证输入的二进制数长度 ≤10。
对于 60%的数据,保证输入的二进制数长度≤1000。
对于 100%的数据,保证输入的二进制数长度 ≤1000000。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	cin >> s;
	int l1=-1,l2=-1,r1=-1,r2=-1;
	for(int i=0;i<s.size();i++)
	{
		if(s[i]=='0')
		{
			if(l1==-1) l1=i;
			else if(l2==-1) l2=i;
		}
	}
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]=='1')
		{
			if(r1==-1) r1=i;
			else if(r2==-1) r2=i;
		}
	}
	string s1=s,s2=s;
	swap(s1[l1],s1[r2]);
	swap(s2[l2],s2[r1]);
	cout << max(s1,s2) << endl;
	return 0;
}

3.

在一次军事演习中,小凯担任通信兵,负责解密传来的信息。他会收到一份 �∗�n∗n 的数字表(仅包含 0−90−9 共 1010 种数码),和一份 �∗�m∗m 的字母表(仅包含A-Za-z 共 5252 种字符)。
数字表被称为解密卡,字母表被称为加密卡。规定如下名词:

1.覆盖区域:将数字表和字母表对齐,使得数字表在上,字母表在下,数字与字母一一对应,如果数字表的 1 行 1 列对应字母表的 x 行 y 列,那么数字表的1+k 行1+k 列对应字母表的x+k 行 y+k 列,此时覆盖区域为字母表以 x 行 y 列为左上角、x+n−1 行y+n−1 列为右下角的正方形范围。简单来说,根据图片显示,若数字表的左上角盖在了 2 行 2列的位置,则数字表会覆盖 (2,2) 到 (3,3) 这片区域。

2.有效区域:称某字母和其在字母表的顺序数字为互相对应,字母 A 和 a 是第 1 个字母、
字母 I 和 i 是第 9 个字母,那么 Aa 和 1 对应,Ii 和 9 对应,以此类推。如果覆盖区域的四个顶点字母恰好和原始数字表的四个顶点数字互相对应,那么这个覆盖区域称之为有效区域。

3.数字关联:0 和任何字母关联,1 不能和任何字母关联,2−9 中的质数和大写字母关联,2−9 中的合数和小写字母关联。若关联成功,则提取出来作为密码的一部分,如上图中 2 是质数,需关联大写字母,2 对应的是 B,关联成功;3 是质数,需关联大写字母,3 对应的 c关联失败;4 是合数,需关联小写字母,而 4 对应的是 D,关联失败。因此上述图中,本次覆盖只关联成功一次,提取出一个密码 B

4.解密数字表:大小为 n∗n,可以由原始数字表顺时针旋转若干次 90° 得到。

5.区域解密:有效区域和解密数字表对齐,从左到右从上到下,将和解密数字表中对应位置数字恰好关联的字母提取出来,构成字符串。一次解密操作包含以下步骤:首先从左到右从上到下找出所有有效区域,依次进行解密。
对于每个有效区域首先用原始数字表进行 1 次区域解密,然后根据当前有效区域的顶点大写字母数量 x,额外进行 x 次区域解密(如图示中四个顶点有两个大写字母,因此需旋转两次),第 i 次解密时将原始数字表顺时针旋转 i∗90° 后作为解密数字表再进行区域解密。最后将所有区域解密的字符串按序连接,构成最终的解密字符串。你需要帮助小凯完成解密工作。

输入共 n+m+1 行,
第 1 行两个正整数 n 和 m,分别代表数字表和字母表的大小;
第 2 至 n+1 行分别有连续的n 个数码字符,代表数字表的内容;
第n+2 至n+m+1 行分别有连续的 m 个字母字符,代表字母表的内容。

输出仅一行一个字符串,代表解密后的答案。如果答案为空串,你需要输出 “No solution”。

对于 30% 的数据,保证输入的 m≤10。
在前 30% 中有 10% 的数据,保证数字表中仅含有 0 和 1。
对于 70% 的数据,保证输入的 m≤50。
在前 70% 中有 30% 的数据,保证字母表中仅含有小写字母。
对于 100% 的数据,保证输入的 n≤m≤300。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
char r[5][305][305];
char l[305][305];
bool ip[10]={0,0,1,1,0,1,0,1,0,0};
string ans;
bool valid(int x,int y)
{
	if(islower(l[x][y]) && l[x][y]-'a'+1!=r[0][1][1]-'0') 
		return false;
	if(isupper(l[x][y]) && l[x][y]-'A'+1!=r[0][1][1]-'0') 
		return false;
	if(islower(l[x][y+n-1]) && l[x][y+n-1]-'a'+1!=r[0][1][n]-'0') 
		return false;
	if(isupper(l[x][y+n-1]) && l[x][y+n-1]-'A'+1!=r[0][1][n]-'0') 
		return false;
	if(islower(l[x+n-1][y]) && l[x+n-1][y]-'a'+1!=r[0][n][1]-'0') 
		return false;
	if(isupper(l[x+n-1][y]) && l[x+n-1][y]-'A'+1!=r[0][n][1]-'0') 
		return false;
	if(islower(l[x+n-1][y+n-1]) && l[x+n-1][y+n-1]-'a'+1!=r[0][n][n]-'0') 
		return false;
	if(isupper(l[x+n-1][y+n-1]) && l[x+n-1][y+n-1]-'A'+1!=r[0][n][n]-'0') 
		return false;
	return true;
}
string rel(int x,int y,int t)
{
	t%=4;
	string s;
	for(int i=x;i<=x+n-1;i++)
	{
		for(int j=y;j<=y+n-1;j++)
		{
			if(r[t][i-x+1][j-y+1]-'0'==1) continue;
			if(r[t][i-x+1][j-y+1]-'0'==0)
				s+=l[i][j];
			else if(ip[r[t][i-x+1][j-y+1]-'0']&&isupper(l[i][j]))
				s+=l[i][j];
			else if(!ip[r[t][i-x+1][j-y+1]-'0']&&islower(l[i][j]))
				s+=l[i][j];
		}
	}
	return s;
}
int main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin >> r[0][i][j];
		}
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin >> l[i][j];
		}
	}
	for(int t=1;t<=3;t++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				r[t][i][j]=r[t-1][n+1-j][i];
			}
		}
	}
	for(int x1=1;x1<=m-n+1;x1++)
	{
		for(int y1=1;y1<=m-n+1;y1++)
		{
			if(!valid(x1,y1)) continue;
			ans+=rel(x1,y1,0);
			int t=bool(isupper(l[x1][y1]))+bool(isupper(l[x1+n-1][y1]))+bool(isupper(l[x1][y1+n-1]))+bool(isupper(l[x1+n-1][y1+n-1]));
			for(int k=1;k<=t;k++)
			{
				ans+=rel(x1,y1,k);
			}
		}
	}
	if(ans=="") ans="No solution";
	cout << ans << endl;
	return 0;
}

本博客到此更新完成,感谢大家的观看!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值