2021级cpp上机练习题第16次(综合练习)

一、赛跑

描述

大柱和黄大佬比赛跑步,黄大佬会把比赛总时间T小时中的s小时拿来睡觉。现在已知比赛总时间T、黄大佬睡觉时间s、黄大佬的跑步速度a、大柱的跑步速度b。问在比赛总时间内谁跑得更远。

输入

一个正整数n,表示有n组案例。

每组案例由4个整数T、s、a、b组成。(1<=T<=1000,0<=s<=T,1<=a<=100,1<=b<=100)

输出

针对每组案例,如果黄大佬跑得远,则输出huang;如果大柱跑得远,则输出dazhu;如果跑得一样远,则输出dual。

每组案例输出完都要换行。

样例输入

2
2 2 2 2
8 4 8 4
 

样例输出

dazhu

dual

关键代码

*****
t = T - s;
xh = t * a;
xd = T * b;
if (xh > xd)
{
	cout << "huang\n";
}
else if (xh < xd)
{
	cout << "dazhu\n";
}
else
{
	cout << "dual\n";
}
*****

解释

通过路程=速度*时间求解。

二、四维

描述

赵大佬做了一款三国题材的手游,需要设计很多架空人物的智力、政治、武力、统率力这四维属性值,以及人物的美工。机智的赵大佬想到了使用同学的考试成绩和照片的方法,拍摄了大柱等很多位同学的美(hei)照,并获取了他们C++、数据结构、算法、语文这四门课的成绩。赵大佬制定了成绩->四维属性值的转换公式:

智力=[(C++)+(算法)]/2

政治=(语文)

武力=(C++)

统率力=[(数据结构)+(算法)]/2

如果上述计算中出现小数部分,则舍弃小数部分。请帮助赵大佬完成这样的转换工作。

输入

一个正整数n,表示有n组案例。

每组案例由4个正整数构成,分别表示C++、数据结构、算法、语文这四门课的成绩。

输出

针对每组案例,输出转换后的智力、政治、武力、统率力这四维属性值,每两个数字之间有一个空格。

每组案例输出完都要换行。

样例输入

2
100 90 85 80
100 100 100 100
 

样例输出

92 80 100 87

100 100 100 100

关键代码

*****
cin >> bc >> sj >> sf >> yw;
zl = (bc + sf) / 2;
zz = yw;
wl = bc;
tsl = (sj + sf) / 2;
cout << zl << ' ' << zz << ' ' << wl << ' ' << tsl << endl;
*****

解释

根据题意分别算出智力、政治、武力、统率力输出即可。

三、积与和

描述

大柱有一次写了两个正整数a和b,告诉赵大佬,a是某两个正整数的和,而b恰好是这两个正整数的积,问这两个正整数分别是多少?(这两个正整数可以是相等的)

输入

一个正整数n,表示有n组案例。

每组案例由两个正整数a和b构成。(1<=a,b<=100000000)

输出

针对每组案例,如果无解,则输出-1;如果有解,则按从小到大顺序输出这两个正整数,两个数字之间有一个空格。

每组案例输出完都要换行。

样例输入

2
9 20
100000000 100000000
 

样例输出

4 5

-1

关键代码

*****
bool flag = false;
for (int j = 1; j < a; j++)
{
	if (j * (a - j) == b)
	{
		flag = true;
		if (j >= (a - j))
		{
			cout << (a - j) << " " << j;
			break;
		}
		else if (j < (a - j))
		{
			cout << j << " " << (a - j);
			break;
		}
	}
}
if (flag == false)
{
	cout << "-1";
}
cout << endl;
*****

解释

flag用来判断有没有两个数刚好符合题意,如果找到了flag=true,就输出两个数,否则就输出-1.根据题意得小的数在前,大的数在后,所以要判断哪个数小,最后换行。

四、打印裙子

描述

女装大佬特别喜欢用星号(*)打出裙子的形状,形状如同一个等腰梯形,第一行有a个星号,然后第二行有a+2个星号(即两侧各多一个星号),第三行有a+4个星号,...,最后一行有b个星号,并且最后一行的星号是顶格的,前面没有空格。每行星号打完后,后面不能再有空格字符。

例如,当a=3,b=9时,输出如下:

 

输入

只有一组案例。

两个正整数a和b(a和b保证要么都是偶数,要么都是奇数,且a<=b)

输出

第一行为a个星号,最后一行为b个星号的形如等腰梯形的形状。注意最后一行的星号是顶格的,前面没有空格。每行星号打完后(包括最后一行),应直接换行,后面不能再有空格字符。

样例输入

2 6
 

样例输出

 

关键代码

*****
for (int i = 1; i <= ((b - a) / 2 + 1); i++)
{
	for (int j = 1; j <= b; j++)
    {
		int x = (b - a) / 2 - i + 1;
		int y = (a + b) / 2 + i - 1;
		if (j <= x)
		{
			cout << " ";
		}
		else if (j > x && j <= y)
		{
			cout << "*";
		}
	}
	cout << endl;
}
*****

解释

观察图片得裙子一共有(b-a)/2+1行,所以外循环输出行,内循环输出列,x、y是记录最后一个空格的位置,y是记录最后一个星号的位置,因为每行最后一个星号打印完后就换行,所以就j<=x才输出空格,否则就输出*,注意等号的位置,最后换行。

五、女装套装

描述

在女装大佬的影响下,很多同学也希望能够通过穿女装的方式提高自己的编程实力。女装大佬手头上有a件上衣,b条裙子和c副假发,每1件上衣+1条裙子+1副假发就可以满足1名同学的女装需求。按照常理,最多能满足的同学数量应该是a、b、c的最小值。

后来来了明杰学长,愿意与女装大佬进行交易,女装大佬可以用任意3样相同类型的服饰,去交换1件其他服饰。例如可以用3件上衣交换1条裙子,也可以用3副假发交换1件上衣,但不可以是2件上衣和1副假发交换1条裙子(因为上衣和假发的类型不同,虽然凑齐了3样)。

已知a、b、c的值,求最多能满足的同学数量。

输入

一个正整数n,表示有n组案例。

每组案例由3个非负整数a、b、c组成。(0<=a<=10000,0<=b<=10000,0<=c<=10000)

输出

针对每组案例,输出一个整数,表示最多能满足的同学数量。

每组案例输出完都要换行。

样例输入

2
5 5 5
5 10 6
 

样例输出

5

6

关键代码

*****
if (a < b)
{
	swap(a, b);
}
if (a < c)
{
	swap(a, c);
}
if (b < c)
{
	swap(b, c);
}
int x = a - c, y = b - c;
if (x < 3)
{
	cout << c;
}
else
{
	while (1)
	{
		if (a - c < e && b - c < 3)
		{
			break;
		}
		a -= 3;
		c += 1;
		if (a < b)
		{
			swap(a, b);
		}
		if (a < c)
		{
			swap(a, c);
		}
		if (b < c)
		{
			swap(b, c);
		}
	}
    cout << c;
}
cout << endl;
*****

解释

首先对a、b、c进行从大到小排列,x记录最多的减去最少的,y同理,然后依照三件换一件的原则进行循环,不足三件的就退出循环,最后拥有的套装数一定是最少的c,最后换行。

六、挂彩灯

描述

有一堆彩灯,红色绿色两种颜色,现在要把它们串在一起,要求每个红灯后面至少要有1个绿灯,求一共有多少种不同的串法

输入

第1行是一个正整数n,表示测试案例的数量

第2到第n+1行是n组测试数据,每行数据有两个正整数,分别表示红灯的数量和绿灯的数量

输出

针对每行测试数据,输出不同的串法数量。(答案不会超过50万)

每组案例输出完都要换行。

样例输入

1
2 3
 

样例输出

3

关键代码

*****
int f(int a, int b)
{
	if (a > b)
	{
        return 0;
    }
	else if (a == b || a == 0)
		{
            return 1;
        }
	else
		{
            return f(a, b - 1) + f(a - 1, b - 1);
        }
}
*****

解释

每个红灯后面必须要有一个绿灯,如果红灯数比绿灯数大,那一定不能成立,返回0。如果红灯数等于绿灯数,那么只有红绿红绿红绿……这一种解法。否则就在红灯后面放一个绿灯,或者放一个红灯之后再放一个绿灯

七、n的阶乘

描述

计算正整数m的阶乘,由于这个数字可能很大,要求输出阶乘对100000007取模的结果

输入

第1行是一个正整数n,表示测试案例的数量。

第2到第n+1行是n组测试数据,每行数据是一个正整数m。

输出

针对每行测试数据,输出m阶乘对100000007取模的结果

样例输入

1
5
 

样例输出

120

关键代码

*****
for (long long i = m - 1; i > 0; i--)
{
	m = ((m % 100000007) * (i % 100000007)) % 100000007;
}
cout << m << endl;
*****

解释

  1. (a + b) % p = (a % p + b % p) % p 

  2. (a - b) % p = (a % p - b % p ) % p 

  3. (a * b) % p = (a % p * b % p ) % p 如果用普通的办法就一个m%100000007一定会超时,所以就要用到以上的公式(注意除法不能用!!!除法有别的公式),用以上的公式既可以防止超时,又可以防止超过longlong数据范围的情况。

八、最大的两个数

描述

在一堆正整数中,把其中最大的两个数输出出来

输入

第1行是一个正整数n,表示测试案例的数量。

从第2行到第n+1行,每行有1个正整数m(2<=m<=1000000),然后是m个正整数。

输出

针对每组测试案例,输出这m个正整数中最大的两个数,先输出最大的,再输出第二大的,两个数之间留一个空格。

每组案例输出完后都要换行。

样例输入

2
4 1 2 3 4
4 1 2 4 4
 

样例输出

4 3

4 4

关键代码

*****
max1 = 0, max2 = 0;
while (m--)
{
	cin >> a;
	if (a >= max1)
	{
		max2 = max1;
		max1 = a;
	}
	else if (a > max2)
	{
		max2 = a;
	}
}
*****

解释

max1储存最大数,max2储存次大数,如果输入的数比max1大,原来max1的数就变成次大数,新输入的数成为最大数,如果输入的数比max1小比max2大,那么新输入的数就是次大数。

九、发好人卡的00

描述

00手上有m张好人卡,每天发1~3张,发完为止,问有多少种发送方法。注意:第一天发1张第二天发2张和第一天发2张第二天发1张,是两种不同的发送方法。

输入

第1行是一个正整数n,表示测试案例的数量。

从第2行到第n+1行,每行有1个正整数m(m<=30)。

输出

针对每组测试案例,输出这m张好人卡发送方法的总数。

每组案例输出完后都要换行。

样例输入

1
3
 

样例输出

4

关键代码

*****
int f(int n)
{
	int x = 0;
	if (n == 1)
	{
		return 1;
	}
	else if (n == 2)
	{
		return 2;
	}
	else if (n == 3)
	{
		return 4;
	}
	else
	{
		return f(n - 1) + f(n - 2) +f(n - 3);
	}
}
*****

解释

最简单的递归题,由题意得一天可以发一张或者两张或者三张,当只有一张好人卡的时候,只有一种可能 返回1;当有两张好人卡的时候有第一天发一张,第二天发一张和第一天发两张两种可能,返回2;当有三张的时候,有第一天发一张,第二天发一张,第三天发一张和第一天发一张,第二天发两张和第一天发两张,第二天发一张和第一天发三张四种可能,返回4;否则就减一张或者减两张或者减三张。

十、天干地支

描述

天干地支,源自中国远古时代对天象的观测。“甲、乙、丙、丁、戊、己、庚、辛、壬、癸”称为十天干,“子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”称为十二地支。天干地支组成形成了古代纪年历法。十干和十二支依次相配,组成六十个基本单位,两者按固定的顺序相互配合,组成了干支纪元法。干支纪元法的一个周期是六十年,以甲子年作为周期的开始,以癸亥年作为周期的结束。

已知1984年是最近的甲子年,称为六十年周期的第1年,那么1985年就是周期的第2年,以此类推。下一个甲子年是2044年,也是周期的第1年。

输入

一个正整数m,表示年份。

输出

一个整数,表示公元m年是干支纪元法一个周期中的第几年。

不要换行。

样例输入

2018
 

样例输出

35

关键代码

*****
if ((year % 60) - 3 == 0)
{
	year = 60;
}
else
{
	year = (year % 60) - 3;
}
*****

解释

通过1984年是甲子年瑞算公元后第一个甲子年是公元3年,所以年份对60取余后要减去三才是他真正的天干地支。

十一、最大的总和

描述

有m个整数,选择其中的一部分(至少1个,至多m个),希望总和越大越好。问这个最大的总和是多少?

输入

一个正整数n,表示有n组案例。

每组案例中,先是一个正整数m(m<=10000),表示数字的个数,然后是m个整数。(保证答案会在int范围内)

输出

针对每组案例,输出一个整数,表示最大的总和。

每组案例输出完都要换行。

样例输入

2
3
-1 2 3
4
1 2 3 4
 

样例输出

5

10

关键代码

*****
f = false;
sum1 = 0, sum2 = INT_MIN;
for (int i = 1; i <= m; i++)
{
	cin >> x;
	if (x >= 0)
	{
		sum1 += x;
		f = true;
	}
	else
	{
		if (x > sum2)
		{
			sum2 = x;
		}
	}
}
if (f)
{
	cout << sum1 << endl;
}
else
{
	cout << sum2 << endl;
}

解释

INT_MIN是int类型的最小值,需要<limits.h>的头文件,这题一分为二来看,1、全是负数——输出最大的负数,2、有正有负——只加正数。f是用来判断输入的数是不是全部都是负数。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值