Contest3412 - 2024寒假集训 进阶训练赛 (十八)(部分题解)

问题 A: 字符串p型编码

题目描述
给定一个完全由数字字符(‘0’,‘1’,‘2’,…,‘9’)构成的字符串str,请写出str的p型编码串。例如:字符串122344111可被描述为"1个1、2个2、1个3、2个4、3个1",因此我们说122344111的p型编码串为1122132431;类似的道理,编码串101可以用来描述1111111111;00000000000可描述为"11个0",因此它的p型编码串即为110;100200300可描述为"1个1、2个 0、1个2、2个0、1个3、2个0",因此它的p型编码串为112012201320。

输入
输入仅一行,包含字符串str。每一行字符串最多包含1000个数字字符。

输出
输出该字符串对应的p型编码串。

AC代码 

#include<bits/stdc++.h>
using namespace std;
int main()
{
	char str[1005];
	cin>>str;
	int cnt=1;//cnt表示相同数字的个数
	for(int i=0;i<strlen(str);i++)
	{
		if(str[i+1]==str[i])//如果后一个数和前一个相同,cnt++
		cnt++;
		else//如果不同则输出,且将cnt记为1
		{
			cout<<cnt<<str[i];
			cnt=1;
		}
	}
}

问题 B: 石头剪刀布 

题目描述
石头剪子布,是一种猜拳游戏。起源于中国,然后传到日本、朝鲜等地,随着亚欧贸易的不断发展它传到了欧洲,到了近现代逐渐风靡世界。简单明了的规则,使得石头剪子布没有任何规则漏洞可钻,单次玩法比拼运气,多回合玩法比拼心理博弈,使得石头剪子布这个古老的游戏同时用于“意外”与“技术”两种特性,深受世界人民喜爱。

游戏规则:石头打剪刀,布包石头,剪刀剪布。

现在,需要你写一个程序来判断石头剪子布游戏的结果。

输入
第一行是一个整数N,表示一共进行了N次游戏。1 ≤ N ≤ 100。

接下来N行的每一行包括两个字符串,表示游戏参与者Player1,Player2的选择(石头、剪子或者是布): S1 S2

字符串之间以空格隔开S1,S2只可能取值在{"Rock", "Scissors", "Paper"}(大小写敏感)中。

输出
输出包括N行,每一行对应一个胜利者(Player1或者Player2),或者游戏出现平局,则输出Tie。 

AC代码 

#include<bits/stdc++.h>
#include<string.h>
using namespace std;

int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		string s1,s2;
		cin>>s1>>s2;
        //简单模拟即可
		if(s1=="Rock")
		{
			if(s2=="Rock")
			cout<<"Tie"<<endl;
			else if(s2=="Scissors")
			cout<<"Player1"<<endl;
			else cout<<"Player2"<<endl;
		}
		if(s1=="Scissors")
		{
			if(s2=="Rock")
			cout<<"Player2"<<endl;
			else if(s2=="Scissors")
			cout<<"Tie"<<endl;
			else cout<<"Player1"<<endl;
		}
		if(s1=="Paper")
		{
			if(s2=="Rock")
			cout<<"Player1"<<endl;
			else if(s2=="Scissors")
			cout<<"Player2"<<endl;
			else cout<<"Tie"<<endl;
		}
	}
}

问题 C: [蓝桥杯2022初赛] 李白打酒加强版 

题目描述
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒 2 斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店 N 次,遇到花 M 次。
已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白这一路遇到店和花的顺序,有多少种不同的可能?
注意:壶里没酒( 0 斗) 时遇店是合法的,加倍后还是没酒;但是没酒时遇花是不合法的。

输入
输入包含多组测试数据。
第一行为T,表示存在T组测试数据,T不超过30。
对于每组测试数据,输入两个整数N 和M.
1 ≤ N, M ≤ 100。 

输出
输出一个整数表示答案。由于答案可能很大,输出模1000000007 的结果。 

AC代码 

前人智慧

问题 E: 今天猛犸不上班

题目描述
临下班之前你对猛犸说:去 猛犸 把这些活干了

猛犸:?你这是&……%*的数字啊?我家数字都是 m进制的
你眼花了吧?你再仔细瞅瞅
给出数字 n ,输出 n 在m 进制下有几位数,让猛犸安安心心上班

输入

1<=n<=10^9,2<=m<=10 

输出
输出一个整数,代表n 在m进制下有几位数 

AC代码

#include<bits/stdc++.h>
#include<string.h>
using namespace std;

int main()
{
	int ans=0,n,m;
	cin>>n>>m;
	while(n!=0)
	{
		n/=m;
		ans++;
	}
	cout<<ans;
}

问题 F: 你干嘛 哈哈嗨呦 

题目描述
有 n 个小朋友坐在一排一起讨论他们共同的某个偶像,相当于一个数轴,每个人的位置坐标是 
a[i],其中一个狂热的粉丝提议,放一张大公鸡的图片摆在他们中间(???)
离我近点~,离我也近点~
由于他们实在是太爱他们的偶像了,甚至接受不了照片离自己远那么一点点
每个人的仇恨值是他们自己的位置和大公鸡距离差值的平方,假设大公鸡的坐标是x ,那么第i 个r人的仇恨值是(x−a[i])^2,要使得所有n个人的仇恨值加一起最小,他们实在是不知道摆在哪了
你能帮帮他们吗

输入
第一行,一个整数,代表n(1≤n≤100)
第二行,n 个整数 ,代表a[i] (1≤a[i]≤100)
接下来输入 n 个数代表每个粉丝的位置

输出
一个整数,代表所有人仇恨值总和的最小值。 

AC代码 

#include<bits/stdc++.h>
#include<string.h>
using namespace std;

int main()
{
	int n,flag;//flag表示公鸡图片需要放的位置 
	int a[105];
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>a[i];
	sort(a,a+n);
	if(n%2==0)//人数为偶数,flag放在最中间两数的中点处 
	flag=(a[n/2]+a[(n/2)-1])/2;
	else flag=a[n/2];//人数为奇数,flag放在最中间的数处 
	int ans=0,ans1=0;
	for(int i=0;i<n;i++)
	{
		ans+=(flag-a[i])*(flag-a[i]);
		ans1+=(flag-1-a[i])*(flag-1-a[i]);//ans1存在是因为在人数为偶数时,存在取中间两数中点的左右问题 
	}
	cout<<min(ans,ans1);//答案为ans和ans1中更小的那个 
}

问题 G: [蓝桥杯2017初赛]日期问题 

题目描述
小明正在整理一批历史文献。这些历史文献中出现了很多日期。
小明知道这些日期都在1960年1月1日至2059年12月31日。
令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。  
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。  
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入 

一个日期,格式是"AA/BB/CC"。  (0 <= A, B, C <= 9)  

输出
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。
多个日期按从早到晚排列。

AC代码 

#include<bits/stdc++.h>
#include<string.h>
using namespace std;
int b1[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年每个月的天数
int b2[12]={31,29,31,30,31,30,31,31,30,31,30,31};//闰年每个月的天数
bool ifrun(int n)//判断是否闰年
{
	if(n%4==0)
	{
		if(n%100==0)
		{
			if(n%400==0)
			return true;
			return false;
		}
	}
	return false;
}
struct date//储存答案的结构体
{
	int y;//年
	int m;//月
	int d;//日
}da[3];
bool cmp(date x1,date x2)//将日期从早到晚排序
{
	if(x1.y==x2.y&&x1.m==x2.m)
	return x1.d<x2.d;
	else if(x1.y==x2.y)
	return x1.m<x2.m;
	else return x1.y<x2.y;
}
int main()
{
	string s;
	cin>>s;
	int a=(s[0]-'0')*10+s[1]-'0';//将输入的字符转为数字
	int b=(s[3]-'0')*10+s[4]-'0';
	int c=(s[6]-'0')*10+s[7]-'0';
	int cnt=0;
	if(b<=12&&b>0)//年月日 
	{
		if(a<=59)//2000年-2059年
		{
			if(ifrun(a+2000))//闰年
			{
				if(c<=b2[b-1])//日符合要求
				{
					da[cnt].y=a+2000;
					da[cnt].m=b;
					da[cnt].d=c;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
			else//平年
			{
				if(c<=b1[b-1])//日符合要求
				{
					da[cnt].y=a+2000;
					da[cnt].m=b;
					da[cnt].d=c;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
		}
		else//1960年-1999年
		{
			if(ifrun(a+1900))
			{
				if(c<=b2[b-1])
				{
					da[cnt].y=a+1900;
					da[cnt].m=b;
					da[cnt].d=c;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
			else
			{
				if(c<=b1[b-1])
				{
					da[cnt].y=a+1900;
					da[cnt].m=b;
					da[cnt].d=c;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
		}
	}
	if(a<=12&&a>0)//月日年 
	{
		if(c<=59)
		{
			if(ifrun(c+2000))
			{
				if(b<=b2[a-1])
				{
					da[cnt].y=c+2000;
					da[cnt].m=a;
					da[cnt].d=b;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
			else
			{
				if(b<=b1[a-1])
				{
					da[cnt].y=c+2000;
					da[cnt].m=a;
					da[cnt].d=b;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
		}
		else
		{
			if(ifrun(c+1900))
			{
				if(b<=b2[a-1])
				{
					da[cnt].y=c+1900;
					da[cnt].m=a;
					da[cnt].d=b;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
			else
			{
				if(b<=b1[a-1])
				{
					da[cnt].y=c+1900;
					da[cnt].m=a;
					da[cnt].d=b;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
		}
	}
	if(b<=12&&b>0)//日月年 
	{
		if(c<=59)
		{
			if(ifrun(c+2000))
			{
				if(a<=b2[b-1])
				{
					da[cnt].y=c+2000;
					da[cnt].m=b;
					da[cnt].d=a;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
			else
			{
				if(a<=b1[b-1])
				{
					da[cnt].y=c+2000;
					da[cnt].m=b;
					da[cnt].d=a;
					cnt++;
					//printf("%d-%02d-%02d\n",a+2000,b,c);
				}
			}
		}
		else
		{
			if(ifrun(c+1900))
			{
				if(a<=b2[b-1])
				{
					da[cnt].y=c+1900;
					da[cnt].m=b;
					da[cnt].d=a;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
			else
			{
				if(a<=b1[b-1])
				{
					da[cnt].y=c+1900;
					da[cnt].m=b;
					da[cnt].d=a;
					cnt++;
					//printf("%d-%02d-%02d\n",a+1900,b,c);
				}
			}
		}
	}
	sort(da,da+cnt,cmp);//从早到晚排序
	for(int i=0;i<cnt;i++)
	{
		if(i!=0&&da[i].y==da[i-1].y&&da[i].m==da[i-1].m&&da[i].d==da[i-1].d)//日期重复则不输出
		continue;
		printf("%d-%02d-%02d\n",da[i].y,da[i].m,da[i].d);//按格式输出
	}
}

问题 H: [蓝桥杯2017初赛]Excel地址 

题目描述
Excel单元格的地址表示很有趣,它使用字母来表示列号。
比如,A表示第1列,B表示第2列,Z表示第26列,AA表示第27列,AB表示第28列,BA表示第53列,....
当然Excel的最大列号是有限度的,所以转换起来不难。
如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?
本题目既是要求对输入的数字, 输出其对应的Excel地址表示方式。

输入
输入存在多组测试数据,对于每组测试数据输入一行包含一个整数
输入的整数范围[1,2147483647] 

输出
对于每组测试数据:输出一行表示答案

 AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
	ll n;
	while(cin>>n)
	{
		string s="";
		while(n!=0)
		{
			int temp=n%26;
			if(temp==0)
			temp=26;
			s+=('A'+temp-1);
			n=(n-temp)/26;
		}
		reverse(s.begin(),s.end());//字符串储存顺序与输出顺序相反
		cout<<s<<endl;
	}
}

问题 J: 简单的大背包

题目描述
你有一个容积为 n 的背包。现有两种物品:
物品1: 价值为1000, 体积为500

物品2: 价值为 5, 体积为5
每种物品的数量是不限的,请问你的背包可以装到物品价值的总和最大是多少?

输入
输入一个整数n,代表背包容积 (0≤n≤10^9) 

输出 

输出一个整数,代表可以取得的最大价值

AC代码 

#include<bits/stdc++.h>
#include<string.h>
using namespace std;

int main()
{
	int n;
	cin>>n;
	int x1=n/500;//第一个物品个数 
	int x2=(n-x1*500)/5;//第二个物品个数 
	cout<<1000*x1+5*x2; 
}

 问题 L: 简单的旅行商

题目描述
我们知道,旅行商问题是一个NP-Hard问题,研究的是图中无重复访问点的最短路径。
我们给定一个周长为C的圆,在圆上有n 个节点.
从圆上某一点开始,沿着一个方向行走,在行走距离ai 后有一个节点i

你可以沿着圆周,从任意方向行走,这样我们就得到一个环状的无向图。
请你在图中找到一条路径,使得每个节点恰好访问一次,且路径长度最短.
请你输出这个最短路径的长度

输入
输入第一行,两个整数,C,n,分别代表圆的周长以及节点个数.
输入第二行,n个递增的整数ai ,代表每个节点在圆上的相对位置. 

(2<=C<=10^6,2<=n<=2*10^5)

(0<=a1<a2<a3<...<an<C)

输出
输出一个整数,代表最短路径长度

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int c,n;
	cin>>c>>n;
	int a[200005],b[200005];
	for(int i=0;i<n;i++)
	cin>>a[i];
	for(int i=0;i<n-1;i++)
	b[i]=a[i+1]-a[i];//表示相邻节点间的距离
	b[n-1]=c-(a[n-1]-a[0]);//表示第一个节点和最后一个节点之间的距离
	sort(b,b+n);//对节点距离排序
	cout<<min(c-b[n-1],a[n-1]);//c-b[n-1]表示周长减去最大的节点间距离,取它和a[n-1]中更小的那个
}

问题 N: 打印文件 

题目描述
黄老师想打印一份有N面的双面文件,其中两面的数据可以打印在一张纸上。

他至少需要多少张纸?

输入
一个整数N,(1<=N<=100)。 

输出
输出答案 

AC代码 

#include<bits/stdc++.h>
#include<string.h>
using namespace std;

int main()
{
	double n;
	cin>>n;
	cout<<ceil(n/2);//向上取整 
}
  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值