2021级C++上机考(下)

2021级C++上机考(下),第1张

2021级C++上机考(下)

*考试没做出来的最后两题花了很久把它做出来(手动哭泣)

六、纳税光荣 描述

某国实行阶梯税率,居民交税时,根据自己的年收入计算需要缴纳的税费。

采用阶梯计费,收入处于0~m1的部分,按r1的比例算该部分的税费;收入处于m1~m2的部分,按r2的比例计算该部分的税费;...;收入处于m5~m6的部分,按r6的比例计算该部分的税费;收入处于超过m6以上的部分,按r7的比例计算该部分的税费。

然后把所有部分的税费累加起来,就是该居民总共应缴纳的税费。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例先是一个正整数a,表示居民的年收入,(a<=5000000)

然后是6个递增的正整数m1、m2、...、m6,(mi<=1000000)

最后是7个非负浮点数r1、r2、...、r7。(均小于1)

输出

针对每组案例,输出一个浮点数,表示该居民应缴纳的税费。精确到小数点后2位。

每组案例输出完要换行。

样例输入

1
200000
36000 144000 300000 420000 660000 960000
0.03 0.1 0.2 0.25 0.3 0.35 0.45
 

样例输出

23080

关键代码
*****
if (a <= m1)
	  ans = a * r1;
else if (a > m1 && a <= m2)
	ans = m1 * r1 + (a - m1) * r2;
else if (a > m2 && a <= m3)
	ans = m1 * r1 + (m2 - m1) * r2 + (a - m2) * r3;
else if (a > m3 && a <= m4)
	ans = m1 * r1 + (m2 - m1) * r2 + (m3 - m2) * r3 + (a - m3) * r4;
else if (a > m4 && a <= m5)
	ans = m1 * r1 + (m2 - m1) * r2 + (m3 - m2) * r3 + (m4 - m3) * r4 + (a - m4) * r5;
else if (a > m5 && a <= m6)
	ans = m1 * r1 + (m2 - m1) * r2 + (m3 - m2) * r3 + (m4 - m3) * r4 + (m5 - m4) * r5 + (a - m5) * r6;
else
	ans = m1 * r1 + (m2 - m1) * r2 + (m3 - m2) * r3 + (m4 - m3) * r4 + (m5 - m4) * r5 + (m6 - m5) * r6 + (a - m6) * r7;
printf("%.2lfn", ans);
*****
解释

这题没什么难点,按照题意将要缴的税算出来,注意每个阶段的多少钱要缴税收以及等号就好了。

七、查找-3 描述

在一个数组中,想要看看是否有三个元素之和等于x,并且要知道总共有多少种不同的选择方法。注意,若a[i]、a[j]、a[k]之和等于x,称为一种选择方法,此时还是这三个下标的元素,调换顺序,例如a[j]、a[k]、a[i]不能称为另一种不同的选择方法。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例先是两个正整数m和x,分别表示数组元素的个数,以及【问题描述】中的x。(3<=m<=100,|x|<=10000)

然后是m个整数。(绝对值均不大于10000)

输出

针对每组案例,如果数组中存在三个元素的和等于x,则输出Yes,然后输出一个空格,后面输出一个整数,表示有多少种不同的选择方法;否则输出No。

每组案例输出完要换行。

样例输入

2
4 10
1 2 3 4
5 10
1 2 3 4 5
 

样例输出

No

Yes 2

关键代码
*****
for (int i = 0; i < m - 2; i++)
{
	for (int j = i + 1; j < m - 1; j++)
	{
		for (int k = j + 1; k < m; k++)
		{
			if (a[i] + a[j] + a[k] == x)
				cnt++;
		}
	}
}
*****
解释

起初我以为三层循环会超时,但是大胆尝试之后就发现不会超时,为了省时间,i其实到m-2,j到m-1就行,这样刚好可以遍历整个数组,寻找有没有三个数字加起来等于x,有就计数cnt++就行了。

八、权重较大的数字 描述

定义一个整数a的权重,是a每位数字的和。例如当a=12345时,a的权重是1+2+3+4+5=15。

这里有个特别的规定,如果同一个数字出现在不同的位上,则算权重时只能算一次。例如当a=512345时,a的权重一样是1+2+3+4+5=15,因为5出现了不止一次,只被算作一次。

如果一个整数是负的,在算权重时不要管负号,就按上述规则计算其对应正数的权重即可。

现在有m个整数,要求按照权重从小到大排序,如果权重相同的数字,则按照数字本身从大到小排序。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例先是一个正整数m,表示整数的数量,(m<=100)

然后是m个整数。(绝对值均不大于1e+8)

输出

针对每组案例,把m个整数优先按照权重从小到大的顺序输出,如果权重相同的数字,则按照数字本身从大到小的顺序输出。

每两个数字之间要有一个空格,最后一个数字后面不要有空格。

每组案例输出完要换行。

样例输入

1
5
12345 512345 -1234555 123 12345678
 

样例输出

123 512345 12345 -1234555 12345678

关键代码
*****
int getq(int n)
{
	n = abs(n);
	int ans = 0;
	int a[10] = { 0 };
	while (n)
	{
		if (a[n % 10] == 0)
		{
			ans = ans + (n % 10);
			a[n % 10] = 1;
		}
		n /= 10;
	}
	return ans;
}
bool cmp(int a, int b)
{
	int a1 = getq(a), b1 = getq(b);
	return a1 < b1 || (a1 == b1 && a > b);
}
*****
sort(num, num + m, cmp);
*****
解释

这道题用sort的第三个参数就显得异常简单,首先第一个getq的函数是获取这个数字的权值,并且用数组标记,保证相同的数字不会再加一遍,。然后是cmp,根据题意按权值从小到大排,如果权值相同,就按数字本身的大小从大到小排,注意获取权值的时候是不用管数字正负,但是比大小的时候要注意数字的正负。这样再在主函数用sort函数就排序成功了。

九、最高得票候选人 描述

有一场班委的选举活动,目前在竞争学习委员。总共有m名同学参与投票,每位同学在投票纸上需要写下两位候选人的姓名,表示投票给这两位候选人各一票。有个特殊规定,如果写下的两个姓名是同一个候选人的,那么额外加一票,相当于该位候选人通过这张选票总共得到了三票。

现在需要知道谁的票数最多。如果有多个候选人票数并列第一,那么选名字在字典序中靠前的。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例先是一个正整数m,表示m名同学参与投票。(m<=100)

然后是m行,表示m张选票上的候选人信息;每行有两个字符串,表示该张选票上两个候选人的名字。注意【问题描述】中的特殊规定。所有候选人的名字都是首字母大写,其余字母小写。

输出

针对每组案例,输出获得票数最多的候选人名字。如果有多个候选人票数并列第一,那么选名字在字典序中靠前的。

每组案例输出完要换行。

样例输入

2
3
Alice Bob
Bob Cathy
David Alice
3
Alice David
Bob Bob
David Alice
 

样例输出

Alice

Bob

关键代码
#include
using namespace std;
struct Student
{
	string name;
	int vote;
};
bool cmp(Student a, Student b)
{
	return a.vote > b.vote || a.vote == b.vote && a.name < b.name;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		Student a[214];
		int m;
		cin >> m;
		int cnt = 0;
		for (int i = 0; i < m; i++)
		{
			string n1, n2;
			cin >> n1 >> n2;
			if (n1 == n2)
			{
				bool flag = 0;
				for (int i = 0; i < 214; i++)
				{
					if (a[i].name == n1)
					{
						a[i].vote += 3;
						flag = 1;
						break;
					}
				}
				if (flag == 0)
				{
					a[cnt].name = n1;
					a[cnt].vote = 3;
					cnt++;
				}
			}
			else
			{
				bool flag = 0;
				for (int i = 0; i < 214; i++)
				{
					if (a[i].name == n1)
					{
						a[i].vote++;
						flag = 1;
						break;
					}
				}
				if (flag == 0)
				{
					a[cnt].name = n1;
					a[cnt].vote = 1;
					cnt++;
				}
				flag = 0;
				for (int i = 0; i < 214; i++)
				{
					if (a[i].name == n2)
					{
						a[i].vote++;
						flag = 1;
						break;
					}
				}
				if (flag == 0)
				{
					a[cnt].name = n2;
					a[cnt].vote = 1;
					cnt++;
				}
			}
		}
		sort(a, a + cnt, cmp);
		cout << a[0].name << endl;
	}
}
解释

这题用到了类的方法(考试的时候用一个数组存名字,一个数组存票数,人整麻了,一直有bug,debug了一个多小时还是没找到,后来想想用类就能将这两个东西联系起来)。用类存名字和得票数,然后是cmp,依然是sort的第三个参数,按照票数为主关键字降序排列,姓名为次关键字升序排列。接着就是创建一个数组,因为每个人能投两个名字,m<100,所以开一个比200大的数组就行,按照一个人投的两票是不是同一个人来分,是的话找到那个人给他的票数+3,如果没找到,就将那个人存入数组中,不是同一个人就分别找,然后给他们的票数+1。最后排序一下,输出a[0]的名字就好了。

十、数列-6 描述

有一个数列已知前2项的值,然后从第3项开始,如果是第奇数项,那么是该项的前两项之和的末6位数;如果是第偶数项,则等于该项的前三项中某两个数字x、y相减的绝对值。其中x是三项中具有最多因数个数的数字,如果三项中有多个并列最多因子个数的数字,取并列的这些数字中比较大的;y是三项中具有最少因子个数的数字,如果三项中有多个并列最少因子的数字,取并列的这些数字中比较小的。

特别规定,0的因子个数等于0。

求数列的第m项的值。

输入

多组案例。一个正整数n,表示案例的数量。(m<=100)

每组案例由三个正整数a、b、m组成,表示数列的第一项、第二项,以及需要计算的是哪一项。(a<=999999,b<=999999,m<=1e+6)

输出

针对每组案例,输出一个整数,表示第m项的值。

每组案例输出完要换行。

样例输入

1
2 6 5
 

样例输出

14

关键代码
#include
using namespace std;
typedef long long ll;
const ll maxn = 1e6 + 14;
int factor[maxn];
int sumFactor(int n)//因数个数(短除法)
{
	int ans = 1;
	for (int i = 2; i * i <= n; i++)
	{
		if (n % i == 0)
		{
			int a = 0;
			while (n % i == 0)
			{
				n /= i;
				a++;
			}
			ans = ans * (a + 1);
		}
	}
	if (n > 1)
		ans *= 2;
	return ans;
}
void getSumFactor()
{
	for (int i = 1; i < maxn; i++)
		factor[i] = sumFactor(i);
}
int f(int a[])
{
	int maxnum = 0, maxf = 0, minnum = 2000000, minf = 2000000;
	for (int i = 0; i < 3; i++)
	{
		if (factor[a[i]] > maxf)
		{
			maxnum = a[i];
			maxf = factor[a[i]];
		}
		else if (factor[a[i]] == maxf)
		{
			if (a[i] > maxnum)
				maxnum = a[i];
		}
		if (factor[a[i]] < minf)
		{
			minnum = a[i];
			minf = factor[a[i]];
		}
		else if (factor[a[i]] == minf)
		{
			if (a[i] < minnum)
				minnum = a[i];
		}
	}
	return abs(maxnum - minnum);
}
int main()
{
	getSumFactor();
	int n;
	scanf("%d", &n);
	while (n--)
	{
		int a, b, m;
		cin >> a >> b >> m;
		int ans[3] = { a,b };
		for (int i = 2; i < m; i++)
		{
			if ((i & 1) == 0)
				ans[i % 3] = (ans[(i - 1) % 3] + ans[(i - 2) % 3]) % 1000000;
			else
				ans[i % 3] = f(ans);
		}
		printf("%dn", ans[(m - 1) % 3]);
	}
}
解释

首先是一个短除法求因数个数,然后是一个预处理,将1000000以内的数的因数放入factor数组中,第三个函数是,寻找前三个数中因数最多的和因数最小的数,返回他们相减的绝对值,然后是主函数,无论是奇数项还是偶数项,只要记住前三个数字就行,所以数组不用开的太大,以免超内存,然后因为是从ans[0]开始存,原来的奇数项就变成了偶数项,原来的偶数项就变成了奇数项,所以要注意改变if的条件,最后再输出就可以了

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5698395.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存