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

问题 A: [蓝桥杯2019初赛]求和

题目描述

小明对数位中含有2、0、1、9 的数字很感兴趣
在1 到40 中这样的数包括1、2、9、10 至32、39 和40,共28 个,他们的和是574。
请问,在1 到2019 中,所有这样的数的和是多少?

输入

无输入

输出

整数 所有满足要求的数之和

代码实现

#include <stdio.h>
int judge(int x)
{
	while(x){
		int r=x%10;
		if(r==2||r==0||r==1||r==9){
			return 1;
		}
		x/=10;
	}
	return 0;
}
int main()
{ 
	int sum=0;
	int i;
	for(i=1;i<=2019;i++){
		if(judge(i)==1){
			sum+=i;
		}
	}
	printf("%d",sum);
	return 0;
 } 

问题 B: [蓝桥杯2015初赛]星系炸弹

题目描述

在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,a年b月c日放置,定时为n天,请你计算它爆炸的准确日期。

输入

输入存在多组数据,每组数据输入一行,每一行输入四个正整数a,b,c,n
输入保证日期在1000-01-01到2020-01-01之间,且日期合法。
n不超过1000

输出

请填写该日期,格式为 yyyy-mm-dd  即4位年份2位月份2位日期。比如:2015-02-19
请严格按照格式书写。不能出现其它文字或符号。

样例输入
2015 1 1 15
2014 11 9 1000
样例输出
2015-01-16
2017-08-05

代码实现

#include <stdio.h>
int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int check(int x)
{//检查是否是闰年 
	if(x%400==0){
		return 1;
	}
	if(x%4==0&&x%100!=0){
		return 1;
	}
	return 0;
}
int main()
{ 
	int a,b,c,n;//a年b月c日放置,定时为n天
	while(scanf("%d %d %d %d",&a,&b,&c,&n)!=EOF){
		int i;
		int r=0;//计算一年当中的剩余天数 
		r+=months[b-1]-c;
		if(check(a)==1&&b<=2&&c<29){
			r++;
		}
		for(i=b;i<=11;i++){
			r+=months[i];
		}
		if(n>r){
			while(n>r){
				n-=r+1;
				a++;
				b=1;
				c=1;
				if(check(a)==1){
					r=365;
				}else{
					r=364;
				}
			}
		}
		if(n==r){
            //year+=1;
            //month=1;day=1;
            printf("%4d-%02d-%02d\n",a,12,31);
            continue;
        }
        if(n<r){
            r=n;
            //printf("%d\n",restday);
            int i;
            for(i=b-1;i<=11;i++){
                if(check(a)==1&&i==1)
                    months[1]=29;
                if(c+r<months[i]){
                    c+=r;
                    r=0;
                    break;
                }
                else if(c+r>months[i]){
                    b++;
                    r-=months[i]-c+1;
                    c=1;
                }else if(c+r==months[i]){
                    r=0;
                    c=months[i];
                    break;
                }
                months[1]=28;
            }
            printf("%4d-%02d-%02d\n",a,b,c);
        }
	}
	return 0;
 } 

问题 C: 查找与给定值最接近的元素

题目描述

在一个非降序列中,查找与给定值最接近的元素

输入

第一行包含一个整数n,为非降序列长度。(1<=n<=100000)
第二行包含n个整数,为非降序列个元素有。所有元素的大小均再0-100000000.
第三行包含一个整数m,为要询问的给定值的个数 1<=m<=10000
接下来的m行,每行一个整数,为要询问最接近的元素的给定值。所有给定值的大小均在0-1000000000.

输出

m行,每行一个整数,为要询问最接近元素的给定值,保持输入顺序。若有多个值满足条件,则输入最小的一个。

样例输入
3
2 5 8
2
10
5
样例输出
8
5

代码实现

#include <stdio.h>
#include <math.h>
int a[1000000];
int BinarySearch(int low,int high,int x)
{
	int mid;
	while(low<high){
		mid=(low+high)/2;
		if(x==a[mid]){
			return mid;
		}else if(x>a[mid]){
			low=mid;
		}else{
			high=mid;
		}
		//当找不到的时候
		if(low+1==high){
			if(abs(x-a[low]>abs(x-a[high]))){
				return high;
			}else{
				return low;
			}
		} 
	}
}
int main()
{
	int n;
	int i;
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	int m;
	scanf("%d",&m);
	for(i=1;i<=m;i++){
		int x;
		scanf("%d",&x);
		int ret=BinarySearch(0,n-1,x);
		printf("%d\n",a[ret]);
	}
	return 0;
 } 

问题 D: 二分解方程

题目描述

输入

输出

对每个样例,输出该方程的一个实数解,小数点后保留四位,如果在0-100无解,就请输出“No solution!”

样例输入
2
100
-4
样例输出
1.6152
No solution!

代码实现

#include<bits/stdc++.h>
using namespace std;
double fn(double x)
{
	return 8*pow(x,4.0)+7*pow(x,3.0)+2*pow(x,2.0)+3*x+6;
}
int main()
{
	int t;
	cin>>t;
		while(t--)
		{
			double y;
			cin>>y;
			double mid;
			if(y>=fn(0)&&fn(100)>=y)
			{
				double left=0;
				double right=100;
				while(right-left>1e-8)
				{
					mid=(left+right)/2;
					if(fn(mid)>y)
					right=mid-1e-9;
					else if(fn(mid)<y)
					left=mid+1e-9;
					else
					break;
				}
				printf("%.4lf\n",(left+right)/2);
			}
			else
				cout<<"No solution!\n";
		}
	return 0;
}

问题 E: 单词的长度

题目描述

输入一行单词序列,相邻单词之间由1个或多个空格间隔,请对应地计算各个单词的长度。注意:如果有标点符号(如连字符,逗号),标点符号算作与之相连的词的一部分。没有被空格间开的符号串,都算作单词。

输入

一行单词序列,最少1个单词,最多300个单词,单词之间用至少1个空格间隔。单词序列总长度不超过1000。

输出

依次输出对应单词的长度,之间以逗号间隔。

样例输入
She was born in 1990-01-02  and  from Beijing city.
样例输出
3,3,4,2,10,3,4,7,5

代码实现

#include <stdio.h>
#define N 1010
char s[N];
int main()
{
	int i,len,cnt=0;
	gets(s);
	for(i=0;s[i]!='\0';i++)
	{
		if(s[i]==' ')
		{
			if(cnt!=0)
				printf("%d,",cnt);
			cnt=0;
		}
		else
		{
			cnt++;
		}
	}
	printf("%d\n",cnt);
	return 0;
}

问题 F: 加密的病历单

题目描述

 小英是药学专业大三的学生,暑假期间获得了去医院药房实习的机会。

 在药房实习期间,小英扎实的专业基础获得了医生的一致好评,得知小英在计算概论中取得过好成绩后,主任又额外交给她一项任务,解密抗战时期被加密过的一些伤员的名单。

   经过研究,小英发现了如下加密规律(括号中是一个“原文 -> 密文”的例子)

   1.原文中所有的字符都在字母表中被循环左移了三个位置(def  -> abc)

   2.逆序存储(abcd -> dcba )

   3.大小写反转(abXY -> ABxy)

输入

一个加密的字符串。(长度小于50且只包含大小写字母)

输出

输出解密后的字符串。

样例输入
GSOOWFASOq
样例输出
Trvdizrrvj

代码实现

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

int main() {
    string a;
    cin >> a;
    int len = a.length();
    for (int i = 0; i < len; i++) {
        if (a[i] <= 'z' && a[i] >= 'a') {
            a[i] -= 32;
        } else if (a[i] <= 'Z' && a[i] >= 'A') {
            a[i] += 32;
        }
    }
    string b;
    for (int i = len - 1; i >= 0; i--) {
        b += a[i];
    }
    for (int i = 0; i < len; i++) {
        if (b[i] != 'x' && b[i] != 'y' && b[i] != 'z' && b[i] != 'X' && b[i] != 'Y' && b[i] != 'Z')
            b[i] += 3;
        else if (b[i] == 'x')
            b[i] = 'a';
        else if (b[i] == 'y')
            b[i] = 'b';
        else if (b[i] == 'z')
            b[i] = 'c';
        else if (b[i] == 'X')
            b[i] = 'A';
        else if (b[i] == 'Y')
            b[i] = 'B';
        else if (b[i] == 'Z')
            b[i] = 'C';
    }
    cout << b << endl;
    return 0;
}

问题 G: [蓝桥杯2015初赛]三羊献瑞

题目描述

观察下面的加法算式:
 


其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。
请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。

输出

请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。

代码实现

#include <iostream>
using namespace std;

int main(){
	int x1,x2,x3,x4;
	int y1,y2,y3,y4;
	int a,b,c;
	int flag[10];
	for(int i=0;i<10;i++)
		flag[i]=0;
	for( x1=0;x1<=9;x1++){
		flag[x1]=1; 
		for(x2=0;x2<=9;x2++){
			if(flag[x2]==1) continue;
			else flag[x2]=1;
			for( x3=0;x3<=9;x3++){
				if(flag[x3]==1) continue;
				else flag[x3]=1;
				for(x4=1;x4<=9;x4++){
					if(flag[x4]==1) continue;
					else flag[x4]=1;
					for(y1=0;y1<=9;y1++){
						if(flag[y1]==1) continue;
						else flag[y1]=1;
						for(y2=0;y2<=9;y2++){
							if(flag[y2]==1) continue;
							else flag[y2]=1;
							for(y3=1;y3<=9;y3++){
								if(flag[y3]==1) continue;
								else flag[y3]=1;
								for(y4=0;y4<=9;y4++){
									if(flag[y4]==1) continue;
									else flag[y4]=1;
									a=x1+10*x2+100*x3+1000*x4;
									b=x3+10*y1+100*y2+1000*y3;
									c=y4+10*x3+100*x2+1000*y2+10000*y3;
									if((a+b)==c) {
										cout<<b;
										break;
										for(int i=0;i<10;i++) flag[i]=0;
									}
									flag[y4]=0;
								}
								flag[y3]=0;
							}
							flag[y2]=0;
						}
						flag[y1]=0;
					}
					flag[x4]=0;
				}
				flag[x3]=0;
			}
			flag[x2]=0;
		}
		flag[x1]=0;
	}
						
	return 0;
}

问题 H: [蓝桥杯2015初赛]生命之树

题目描述

在X森林里,上帝创建了生命之树。
他给每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值。
上帝要在这棵树内选出一个非空节点集S,使得对于S中的任意两个点a,b,都存在一个点列


使得这个点列中的每个点都是S里面的元素,且序列中相邻两个点间有一条边相连。
在这个前提下,上帝要使得S中的点所对应的整数的和尽量大。
这个最大的和就是上帝给生命之树的评分。
经过atm的努力,他已经知道了上帝给每棵树上每个节点上的整数。
但是由于 atm 不擅长计算,他不知道怎样有效的求评分。
他需要你为他写一个程序来计算一棵树的分数。

输入

第一行一个整数 n 表示这棵树有 n 个节点。


第二行 n 个整数,依次表示每个节点的评分。(每个节点的评分不超过

)
接下来 n-1 行,每行 2 个整数 u, v,表示存在一条 u 到 v 的边。
由于这是一棵树,所以是不存在环的。

输出

输出一行一个数,表示上帝给这棵树的分数。

样例输入
5
1 -2 -3 4 5
4 2
3 1
1 2
2 5
样例输出
8

代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
vector<int>G[N];
ll dp[N][2],val[N],ans;
int n;
 
void dfs1(int u,int fa)
{
    dp[u][1]=val[u];
    for(int v:G[u]){
        if(v==fa) continue;
        dfs1(v,u);
        dp[u][1]+=max({dp[v][1],dp[v][0]});
        dp[u][0]+=dp[v][0];
    }
    ans=max({dp[u][1],dp[u][0],ans});
}
 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lld",&val[i]);
    for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,-1);
    printf("%lld\n",ans);
    return 0;
}

问题 I: Dongdziz与不说阿拉伯语的阿拉伯商人

题目描述

Dongdziz到一个阿拉伯人开的商店购物。

这个阿拉伯人会卖个游戏,每个游戏都有个标号,比如3号游戏标号就是3,号游戏标号就是

(1开始计算标号),但是每个游戏的价格是这么算的,价格=游戏标号*买家的年龄A+游戏标号的位数*商人的年龄B

不用担心,我们会知道dongdziz哥哥的年龄和商人的年龄的

问题来了,dongdziz今天钱包里只有x元钱,问能最买的标号最大的游戏是哪个呢?

如果哪个游戏都买不了,那么请输出0

输入

输出
能最买的标号最大的游戏的标号
样例输入
10 7 100
样例输出
9

代码实现

#include<bits/stdc++.h>
using namespace std;
 
typedef long long ll;
 
int main()
{
    ios::sync_with_stdio(false); 
    cin.tie(0);
    cout.tie(0);
    ll a,b,x;
    cin>>a>>b>>x;
    if(x<a+b){
        cout<<0;
        return 0;
    }
    ll ans=0;
    for(int i=1;i<=10;i++){
        ll t=(x-i*b)/a;
        if(t>=pow(10,i)){
            t=pow(10,i)-1;
        }
        ans=max(ans,t);
    }
    ans=min(ans,(ll)1000000000);
    cout<<ans;
}

问题 J: 回文游戏

题目描述

回文串是指对称的字符串,如ababa是回文串,因为它反过来读还是ababa;abc不是回文串,因为其反过来读是cba,与abc不同;
给你一个字符串S,
你可以修改S的任意一个字符,
问最少需要修改多少次,使得S变成一个回文串。

输入

字符串S
1<=长度<=100

输出

最少需要修改多少次,使得S变成一个回文串。

样例输入
redcoder
样例输出
1

代码实现

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int count=0;
    string s;
    cin>>s;
    int len=s.length();
    for(int i=0;i<len;i++){
        if(s[i]!=s[len-i-1]) count++;
    }
    cout<<count/2<<endl;
 
 
    return 0;
}

问题 K: 2.4.2 Web导航

题目描述

标准的 Web 浏览器包含在最近访问过的页面中向后和向前移动的功能。实现这些特性的一种方法是使用两个栈来跟踪前后移动可以到达的页面。支持以下命令。
BACK:将当前页面推到前向栈的顶部。从后向栈的顶部弹出页面,使其成为新的当前页面。如果后向栈为空,则忽略该命令。
FORWARD:将当前页面推到后向栈的顶部。从前向栈顶部弹出页面,使其成为新的当前页面。如果前向栈为空,则忽略该命令。
VISIT:将当前页面推到后向栈的顶部,使得 URL 成为新的当前页面,前向栈清空。
QUIT:退出浏览器。
假设浏览器的最初页面为 URL ***###.acm.org/ (对 "http://" 用 "***" 代替,对 "www" 用 "###" 代替)。

输入

输入是一系列 BACK、FORWARD、VISIT、QUIT 命令。

输出

对于除了 QUIT 外的每个命令,如果不忽略该命令,则在执行该命令后单行输出当前页的 URL,否则输出 "Ignored"。
QUIT 命令没有输出。

样例输入 复制
VISIT ***acm.ashland.edu/
VISIT ***acm.baylor.edu/acmicpc/
BACK
BACK
BACK
FORWARD
VISIT ***###.ibm.com/
BACK
BACK
FORWARD
FORWARD
FORWARD
QUIT
样例输出 复制
***acm.ashland.edu/
***acm.baylor.edu/acmicpc/
***acm.ashland.edu/
***###.acm.org/
Ignored
***acm.ashland.edu/
***###.ibm.com/
***acm.ashland.edu/
***###.acm.org/
***acm.ashland.edu/
***###.ibm.com/
Ignored
提示

URL 没有空白,最多有 70 个字符。
任何时候,在每个栈中都不会超过 100 个元素。
QUIT 命令表示输入结束。

代码实现

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string order;
	string page[100];
	page[0]="***###.acm.org/";
	int i=0;
	int max=0;
	while(getline(cin,order))
	{
		if(order[1]=='Q')
		break;
		else
		{
			if(order[4]=='T')
			{
				i++;
				page[i]=order.substr(6);
				cout<<page[i]<<endl;
				max=i;
			}
			if(order[0]==66)
			{
				if(i==0)
				cout<<"Ignored"<<endl;
				else
				{
					i--;
					cout<<page[i]<<endl;
				}
			}
			if(order[0]==70)
			{
				if(max<i+1)
				cout<<"Ignored"<<endl;
				else
				{
					i++;
					cout<<page[i]<<endl;
				}
			}
		}
	}
}

问题 L: 2.4.3 骑士移动

题目描述

写程序,计算象棋中马从一个位置移动到另一个位置所需的最少移动次数。

输入

有多组测试数据。

第一行一个整数 T,代表数据组数。
每组数据包含三行。
第一行表示棋盘的长度 L,棋盘大小为 L×L。
第二行包含两个整数 x, y,表示马的起始位置坐标。
第三行包含两个整数 a, b,表示马的终点位置坐标。
L 最大为 300。
棋盘坐标范围为 [0, ..., L-1]。

 

输出

对于每组数据输出一行,包含一个数字,即最少移动次数。
若起点终点相同,则移动次数为 0。

样例输入 复制
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
样例输出 复制
5
28
0
提示

马走日!!!
数据保证可以到终点,不用额外判断无法走到终点的情况。

代码实现

问题 M: 大食堂

题目描述
输入

 
输出

输出一个数,代表最小花费。

样例输入 复制
3 5
4 2 1
1 2 3
样例输出 复制
2
提示

代码实现

问题 N: 吃菜

题目描述

输入

输出

最后能够得到的最大美味度是多少。

样例输入 复制
2 60
10 10
100 100
样例输出 复制
110
提示

代码实现

问题 O: 矩形

题目描述


输入

样例输入 复制
3
1 1
5 1
5 5
样例输出 复制
1
提示

代码实现

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值