蓝桥杯日常训练题(第一次训练题)

蓝桥杯日常训练题

链接https://vjudge.net/contest/389509
密码:dlxy888888
主要算法
a 递归
b 数学
c 递归
d 快速查找因子
e 进制转换
f 水
g 大数相加算法
h 动态规划
i 贪心加优先队列
j 遍历算法
k 动态规划

A - 杨辉三角

还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
Input
输入数据包含多个测试实例,每个测试实例的输入只包含一个正整数n(1<=n<=30),表示将要输出的杨辉三角的层数。
Output
对应于每一个输入,请输出相应层数的杨辉三角,每一层的整数之间用一个空格隔开,每一个杨辉三角后面加一个空行。
Sample Input
2 3
Sample Output
1
1 1

1
1 1
1 2

#include<iostream>
#include<vector>
using namespace std;
int main() {
	vector<vector<int> > a(50,vector<int>(50));
	for (int i = 0; i < 40; i++) {
		a[i][0] = 1;
		a[i][i] = 1;
	}
	for (int i = 2; i < 40; i++) {
		for (int j = 1; j < i; j++) {
			a[i][j] = a[i - 1][j] + a[i - 1][j - 1];
		}
	}
	int n;
	while (cin >> n) {
		int i, j;
		for ( i = 0; i < n; i++) {
			for (j = 0; j < i; j++) {
				cout << a[i][j] << " ";
			}cout << a[i][j];
			cout << endl;
		}
		cout << endl;
	}
	return 0;
}

B - a/b + c/d

给你2个分数,求他们的和,并要求和为最简形式。
Input
输入首先包含一个正整数T(T<=1000),表示有T组测试数据,然后是T行数据,每行包含四个正整数a,b,c,d(0<a,b,c,d<1000),表示两个分数a/b 和 c/d。
Output
对于每组测试数据,输出两个整数e和f,表示a/b + c/d的最简化结果是e/f,每组输出占一行。
Sample Input
2
1 2 1 3
4 3 2 3
Sample Output
5 6
2 1

#include<iostream>
using namespace std;
int gcd(int a, int b) {
	if (b == 0)return a;
	else return gcd(b, a%b);
}
int main() {
	int T,a,b,c,d;
	cin >> T;
	while (T--) {
		cin >> a >> b >> c >> d;
		int fenzi, fenmu;
		fenzi = a * d + b * c;
		fenmu = b * d;
		int x = gcd(fenzi, fenmu);
		cout << fenzi / x << " " << fenmu / x << endl;
	}
	return 0;
}

C - 超级楼梯

有一楼梯共M级 ,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
Input
输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。
Output
对于每个测试实例,请输出不同走法的数量
Sample Input
2
2
3
Sample Output
1
2

#include<iostream>
using namespace std;
int f(int n) {
	if (n == 1)return 1;
	if (n == 2) return 1;
	if (n == 3)return 2;

	return f(n - 1) + f(n - 2);
} 
int main() {
	int T, n;
	cin >> T;
	while (T--) {
		cin >> n;
		cout << f(n) << endl;
	}
	return 0;
}

D - 七夕节

七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:“你们想知道你们的另一半是谁吗?那就按照告示上的方法去找吧!”
人们纷纷来到告示前,都想知道谁才是自己的另一半.告示如下:
在这里插入图片描述

数字N的因子就是所有比N小又能被N整除的所有正整数,如12的因子有1,2,3,4,6.
你想知道你的另一半吗?
Input
输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字N(1<=N<=500000).
Output
对于每组测试数据,请输出一个代表输入数据N的另一半的编号.
Sample Input
3
2
10
20
Sample Output
1
8
22

#include<iostream>
using namespace std;
int f(int n) {
	int ans = 0,i=0;
	for (i = 2; i*i < n; i++) {
		if (n%i == 0) {
			ans = ans + i+n/i;
		}
	}
	if (i*i == n) {
		ans += i;
	}
	return ans+1;
} 
int main() {
	int T, n;
	cin >> T;
	while (T--) {
		cin >> n;
		cout << f(n) << endl;
	}
	return 0;
}

E - 进制转换

输入一个十进制数N,将它转换成R进制数输出。
Input
输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。
Output
为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,等等)。
Sample Input
7 2
23 12
-4 3
Sample Output
111
1B
-11

#include<iostream>
#include<stack>
using namespace std;
char f(int n) {
	if (n == 10)return 'A';
	if (n == 11)return 'B';
	if (n == 12)return 'C';
	if (n == 13)return 'D';
	if (n == 14)return 'E';
	if (n == 15)return 'F';
}
int main() {
	int n, r;
	while (cin >> n >> r) {
		stack<int> s;
		if (n < 0) {
			cout << '-';
		}
		n = abs(n);
		while (n != 0) {
			s.push(n%r);
			n /= r;
		}
		while (!s.empty()) {
			int tes = s.top();
			if (tes < 10) {
				cout << tes;
			}
			else {
				cout << f(tes);
			}
			s.pop();
		}
		cout << endl;
	}
	return 0;
}

F - The calculation of GPA

每学期的期末,大家都会忙于计算自己的平均成绩,这个成绩对于评奖学金是直接有关的。国外大学都是计算GPA(grade point average) 又称GPR(grade point ratio),即成绩点数与学分的加权平均值来代表一个学生的成绩的。那么如何来计算GPA呢?

一般大学采用之计分法

A90 - 100 4 点
B80 - 89 3 点
C70 - 79 2 点
D60 - 69 1 点
E0 - 59 0 点

例如:某位学生修习三门课,其课目、学分及成绩分别为:
英文:三学分、92 分;化学:五学分、80 分;数学:二学分、60分,则GPA的算法如下:

科目 学分 分数 点数 分数×点数
英文 3 92 4 12
化学 5 80 3 15
数学 2 60 1 2
合计 10 29
29/10=2.9
2.9即为某生的GPA
下面有请你写一个用于计算GPA的程序。
Input
包含多组数据,每组数据的第一行有一个数N,接下来N行每行表示一门成绩。每行有两个实型的数 s,p,s表示这门课的学分,p表示该学生的成绩(百分制)。如果p=-1则说明该学生这门课缺考,是不应该计算在内的。
Output
对每组数据输出一行,表示该学生的GPA,保留两位小数。如果GPA不存在,输出-1。
Sample Input
3
3 92
5 80
2 60
Sample Output
2.90

#include <cstdio>
#include <iomanip>
#include<cstring>
#include<iostream>
using namespace std;
struct Node
{
	double s;
	double p;
	double gp;
}a[1000000];
int main()
{
	int n;
	while (cin>>n)
	{
		memset(a, 0, sizeof(a));
		for (int i = 0; i < n; ++i)
		{
			cin >> a[i].s >> a[i].p;
			if (a[i].p != -1)
			{
				if (a[i].p >= 90.0)
					a[i].gp = 4 * a[i].s;
				else if (a[i].p >= 80.0)
					a[i].gp = 3 * a[i].s;
				else if (a[i].p >= 70.0)
					a[i].gp = 2 * a[i].s;
				else if (a[i].p >= 60.0)
					a[i].gp = 1 * a[i].s;
			}
		}
		double sums = 0;
		double sump = 0;
		for (int i = 0; i < n; ++i)
		{
			sums += a[i].s;
			if (a[i].p != -1)
			{
				sump += a[i].gp;
			}
		}
		if (sump)
			cout <<fixed<<setprecision(2)<< sump / sums << endl;
		else
			cout << -1 << endl;
	}
}

G - 大菲波数

Fibonacci数列,定义如下:
f(1)=f(2)=1
f(n)=f(n-1)+f(n-2) n>=3。
计算第n项Fibonacci数值。
Input
输入第一行为一个整数N,接下来N行为整数Pi(1<=Pi<=1000)。
Output
输出为N行,每行为对应的f(Pi)。
Sample Input
5
1
2
3
4
5
Sample Output
1
1
2
3
5

#include<iostream>
using namespace std;
int a[1010][550];
int main()
{
	int s, c;
	a[1][0] = 1; a[2][0] = 1;
	for (int i = 3; i < 1001; i++)
	{
		c = 0;
		for (int j = 0; j <= 500; j++) /*以下步骤模拟大数计算,初始化斐波那契数列*/
		{
			s = a[i - 1][j] + a[i - 2][j] + c;
			a[i][j] = s % 10;
			c = s / 10;
		}
	}
	int n, p, i;
	cin >> n;
	while (n--)
	{
		cin >> p;
		for (i = 500; i >= 0; i--)    /*找到数值的最后一位 */
		{
			if (a[p][i])
				break;
		}
		for (; i >= 0; i--)// 注意上面的函数计算的值的数位是逆序的
		{
			cout << a[p][i];
		}cout << endl;
	}
	return 0;
}

H - 整数划分

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1>=n2>=…>=nk>=1。正整数n的这种表示称为正整数n的划分。求正整数n的不同划分个数。例如,正整数6有如下11种不同的划分:6: 6; 5+1; 4+2; 4+1+1; 3+3; 3+2+1; 3+1+1+1; 2+2+2; 2+2+1+1; 2+1+1+1+1; 1+1+1+1+1+1.
Input
多组测试数据,输入到文件结束,每组数据包含一个正整数n(n<=40)
Output
输出n的不同划分个数。
Sample Input
3
6

Sample Output
3
11

#include<iostream>
#include<algorithm>
using namespace std;
int f[50][50], a[50];
int main() {
	int n;

	while (!(cin >> n).eof()) {
		f[0][0] = 1;
		int ans = 0;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (i == 1 || j == 1) {
					f[i][j] = 1;
				}
				else
					if (i < j) {
						f[i][j] = f[i][i];
					}
					else
						if (i == j) {
							f[i][j] = f[i][j - 1] + 1;
						}
						else {
							f[i][j] = f[i][j - 1] + f[i - j][j];
						}
			}
		}
		cout << f[n][n] << endl;
	}
	return 0;
}

I - 湫湫系列故事——消灭兔子

湫湫减肥
  越减越肥!
  
  最近,减肥失败的湫湫为发泄心中郁闷,在玩一个消灭免子的游戏。
  游戏规则很简单,用箭杀死免子即可。
  箭是一种消耗品,已知有M种不同类型的箭可以选择,并且每种箭都会对兔子造成伤害,对应的伤害值分别为Di(1 <= i <= M),每种箭需要一定的QQ币购买。
  假设每种箭只能使用一次,每只免子也只能被射一次,请计算要消灭地图上的所有兔子最少需要的QQ币。
Input
输入数据有多组,每组数据有四行;
第一行有两个整数N,M(1 <= N, M <= 100000),分别表示兔子的个数和箭的种类;
第二行有N个正整数,分别表示兔子的血量Bi(1 <= i <= N);
第三行有M个正整数,表示每把箭所能造成的伤害值Di(1 <= i <= M);
第四行有M个正整数,表示每把箭需要花费的QQ币Pi(1 <= i <= M)。

特别说明:
1、当箭的伤害值大于等于兔子的血量时,就能将兔子杀死;
2、血量Bi,箭的伤害值Di,箭的价格Pi,均小于等于100000。
Output
如果不能杀死所有兔子,请输出”No”,否则,请输出最少的QQ币数,每组输出一行。
Sample Input
3 3
1 2 3
2 3 4
1 2 3
3 4
1 2 3
1 2 3 4
1 2 3 1
Sample Output
6
4

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node {
	int di, pi;
}arr[100005];
int B[100005];
bool cmp1(node a, node b) {
	return a.di > b.di;
}//对箭使用
bool cmp2(int a, int b) {
	return a > b;
}//对兔子的血量使用
int main() {
	int n, m;
	while (cin >> n >> m) {
		for (int i = 0; i < n; i++) {
			cin >> B[i];
		}
		for (int i = 0; i < m; i++) {
			cin >> arr[i].di;
		}
		for (int i = 0; i < m; i++) {
			cin >> arr[i].pi;
		}
		sort(B, B + n, cmp2);
		sort(arr, arr + m, cmp1);
		int j = 0, flag = 0;
		long long price = 0;
		priority_queue<int,vector<int>,greater<int> > q;
		for (int i = 0; i < n; i++) {
			while (arr[j].di >= B[i] && j < m) {
				q.push(arr[j].pi);
				j++;
			}
			if (q.empty()) {
				flag = 1;
				break;
			}
			price += q.top();
			q.pop();
		}
		if (flag)cout << "No" << endl;
		else cout << price << endl;
	}
	return 0;
}

J - 马走日

马在中国象棋以日字形规则移动。

请编写一段程序,给定
n
×
m
大小的棋盘,以及马的初始位置
(
x
,
y
)
,要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。

输入格式
第一行为整数
T
(
T
<
10
)
,表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标
n
,
m
,
x
,
y
。(
0

x

n

1
,
0

y

m

1
,
m
<
10
,
n
<
10
)。

输出格式
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,
0
为无法遍历一次。

Sample Input
1
5 4 0 0
Sample Output
32

#include<iostream>
#include<cstring>
using namespace std;
char map[11][11];
int vis[11][11];
int x, y, n, m;
int dir[8][2] = { {-2,1},{-2,-1},{2,-1},{2,1},{-1,2} ,{-1,-2} ,{1,-2} ,{1,2} };
int cnt;
void dfs(int x, int y, int step) {
	if (step == n * m) {
		cnt++;
		return;
	}
	for (int i = 0; i < 8; i++) {
		int tx = x + dir[i][0];
		int ty = y + dir[i][1];
		if (tx >= 0 && tx < n&&ty >= 0 && ty < m&&vis[tx][ty] == 0) {
			vis[tx][ty] = 1;
			dfs(tx, ty, step + 1);
			vis[tx][ty] = 0;
		}
	}
};
int main() {
	int t;
	cin >> t;
	while (t--) {
		cnt = 0;
		memset(vis, 0, sizeof(vis));
		cin >> n >> m >> x >> y;
		vis[x][y] = 1;
		dfs(x, y, 1);
		cout << cnt << endl;
	}
	return 0;
}

K - 最大连续子序列

给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …,
Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,
例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和
为20。
在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该
子序列的第一个和最后一个元素。
Input
测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( < 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元
素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。
Sample Input
6
-2 11 -4 13 -5 -2
10
-10 1 2 3 4 -5 -23 3 7 -21
6
5 -8 3 2 5 0
1
10
3
-1 -5 -2
3
-1 0 -2
0
Sample Output
20 11 13
10 1 4
10 3 5
10 10 10
0 -1 -2
0 0 0

#include<iostream>
using namespace std;
long long int a[10005];
int main() {
	int n;
	while (cin >> n&&n) {
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}
		long long int sum = 0,ans=LLONG_MIN;
		int ts=0, s=0, e=0;
		for (int i = 0; i < n; i++) {
			sum += a[i];
			if (ans < sum) {
				ans = sum;
				e = i;
				s = ts;
			}
			if (sum < 0) {
				sum = 0;
				ts = i + 1;
			}
		}
		if (ans < 0) {
			cout << 0<< " " << a[0] << " " << a[n - 1] << endl;
		}
		else {
			cout << ans << " " << a[s] << " " << a[e] << endl;
		}
	}return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值