“计算机程序设计能力考试(乙级)”真题刷题
十六、题目:1016 部分A+B (15 分)
正整数 A 的“DA(为 1 位整数)部分”定义为由 A 中所有 D
A 组成的新整数 PA 。例如:给定 A=3862767,DA =6,则 A的“6 部分”PA 是 66,因为 A 中有 2 个 6。现给定 A、D 、B、DB ,请编写程序计算 PA +PB 。
输入格式:
输入在一行中依次给出 A、DA、B、DB ,中间以空格分隔,其中 0<A,B<109 。
输出格式:
在一行中输出 PA +PB 的值。
输入样例 1:
3862767 6 13530293 3
输出样例 1:
399
输入样例 2:
3862767 1 13530293 8
输出样例 2:
0
1.代码
#include<iostream>
using namespace std;
int partion(int A, int D) {
int i, a,temp;
i = a =temp= 0; //i作为temp的幂次,temp为10*i次幂,a存取各位上的数
int result = D; //引入结果变量,一开始把D存为结果,导致下面while循环出错,妈的
while (A > 0) {
a = A % 10;
if (a == D) {
result = a * temp + result;
i++;
temp = pow(10, i);
}
A = A / 10;
}
if (i== 0) //i如果为0,证明没有进入if(a==D)判断语句过
return 0;
else
return result;
}
int main() {
int A, D1, B, D2;
cin >> A >> D1 >> B >> D2;
cout << partion(A, D1)+ partion(B, D2) << endl;
system("pause");
return 0;
}
2.心得
题目不难,但是一些细节原因,害我搞了半个小时无用过、、、
十七、题目:1017 A除以B (20 分)
本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。
输入格式:
输入在一行中依次给出 A 和 B,中间以 1 空格分隔。
输出格式:
在一行中依次输出 Q 和 R,中间以 1 空格分隔。
输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3
1.代码
大自然的搬运工,这是链接
#include <stdio.h>
int main() {
char a[1001];
int b = 0;
int s[1001];
int i = 0, len = 0, r = 0;
scanf("%s %d", a, &b);
for (i = 0; a[i] != '\0'; ++i) {
s[i] = a[i] - '0';
}
len = i;
for (int j = 0; j < len; ++j) {
if (j != 0 || s[j] / b != 0) {
printf("%d", (10 * r + s[j]) / b);
}
r = (10 * r + s[j]) % b;
}
if (len == 1 && s[0] < b) {
printf("0");
}
printf(" %d", r);
int temp = 0, x = 0, y = 0;
return 0;
}
2.心得
对于操纵很大的数据时,可以学会用字符数组去实现操纵,然后通过重写运算符实现功能。
十八、题目:1018 锤子剪刀布 (20 分)
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
输入格式:
输入第 1 行给出正整数 N(≤10
5
),即双方交锋的次数。随后 N 行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”,第 1 个字母代表甲方,第 2 个代表乙方,中间有 1 个空格。
输出格式:
输出第 1、2 行分别给出甲、乙的胜、平、负次数,数字间以 1 个空格分隔。第 3 行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有 1 个空格。如果解不唯一,则输出按字母序最小的解。
输入样例:
10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J
输出样例:
5 3 2
2 3 5
B B
1.代码
#include <iostream>
#include <string>
#include<iostream>
using namespace std;
struct gen
{
//记录"J"赢的次数
int j;
//记录"C"赢的次数
int c;
//记录"B"赢的次数
int b;
};
int main()
{
int n;
cin>>n;
string str_1,str_2;
//定义甲、乙结构体,分别储存使用不同手势赢的次数
gen play_1;
gen play_2;
play_1.j=0;
play_1.c=0;
play_1.b=0;
play_2.j=0;
play_2.c=0;
play_2.b=0;
for (int i = 0; i < n; i++)
{
cin>>str_1>>str_2;
if (str_1=="J"&&str_2=="C")
{
play_2.c++;
}
else if(str_1=="J"&&str_2=="B")
{
play_1.j++;
}
else if(str_1=="C"&&str_2=="J")
{
play_1.c++;
}
else if(str_1=="C"&&str_2=="B")
{
play_2.b++;
}
else if(str_1=="B"&&str_2=="J")
{
play_2.j++;
}
else if(str_1=="B"&&str_2=="C")
{
play_1.b++;
}
}
//a:甲赢的次数,b:乙赢的次数
int a=0,b=0;
a=play_1.j+play_1.c+play_1.b;
b=play_2.j+play_2.c+play_2.b;
//c:平的次数
int c=n-a-b;
cout<<a<<" "<<c<<" "<<n-a-c<<"\n";
cout<<b<<" "<<c<<" "<<n-b-c<<"\n";
//给出甲获胜出现的最多的手势,解不唯一,则输出按字母序最小的解
if (play_1.j>play_1.c)
{
if (play_1.j>play_1.b)
{
cout<<"J"<<" ";
}
else
{
cout<<"B"<<" ";
}
}
else
{
if (play_1.c>play_1.b)
{
cout<<"C"<<" ";
}
else
{
cout<<"B"<<" ";
}
}
//给出乙获胜出现的最多的手势,解不唯一,则输出按字母序最小的解
if (play_2.j>play_2.c)
{
if (play_2.j>play_2.b)
{
cout<<"J";
}
else
{
cout<<"B";
}
}
else
{
if (play_2.c>play_2.b)
{
cout<<"C";
}
else
{
cout<<"B";
}
}
return 0;
}
2.心得
好像上学期有学过这道题,温故知新~
十九、题目:1019 数字黑洞 (20 分)
给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的 6174,这个神奇的数字也叫 Kaprekar 常数。
例如,我们从6767开始,将得到
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
… …
现给定任意 4 位正整数,请编写程序演示到达黑洞的过程。
输入格式:
输入给出一个 (0,10
4
) 区间内的正整数 N。
输出格式:
如果 N 的 4 位数字全相等,则在一行内输出 N - N = 0000;否则将计算的每一步在一行内输出,直到 6174 作为差出现,输出格式见样例。注意每个数字按 4 位数格式输出。
输入样例 1:
6767
输出样例 1:
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
输入样例 2:
2222
输出样例 2:
2222 - 2222 = 0000
1.代码
#include<iostream>
#include<string.h> //string
#include<algorithm> //sort
#include<math.h> //pow
using namespace std;
int main()
{
string str;
int a[4]={0,0,0,0};
int d=0,x=0,cha=0; //较大值 较小值初始化 输入值
cin>>str;
int len=str.length();
for(int i=0;i<len;i++){
a[i]=str[i]-'0';
}
if (a[1]==a[2]&&a[2]==a[3]&&a[3]==a[0]) {
cout<<str<<" - "<<str<<" = "<<"0000"; //这样写如果0000不带引号的话,第一个测试点错误
// printf("%04d - %04d = %04d\n",a[0]*1111,a[0]*1111,0);
}
else{
while(cha!=6174)
{
sort(a,a+4,greater<int>());
for(int i=0;i<4;i++){
d=10*d+a[i];
x=10*x+a[3-i]; //注意789 应该表示为0789
}
cha= d-x;
// cout<<d<<" - "<<x<<" = "<<cha<<endl; //可能是3210-123 格式错误
printf("%04d - %04d = %04d\n",d,x,cha);
a[3]=cha%10;
a[2]=(cha/10)%10;
a[1]=(cha/100)%10;
a[0]=cha/1000;
d=0;
x=0;
}
}
return 0;
}
2.心得
以后对于格式化输出有了新的办法了:printf()!!!
printf("%04d %04d",520,1314);
//输出:0520 1314
二十、题目:1020 月饼 (25 分)
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。
输入样例:
3 20
18 15 10
75 72 45
输出样例:
94.50
1.代码
#include <iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn = 1001;
struct st
{
double a;
double b;
double p;
} k[maxn];
bool cmp(st a1, st b1)
{
return a1.p > b1.p;
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> k[i].a;
}
for (int i = 1; i <= n; i++)
{
cin >> k[i].b;
}
for (int i = 1; i <= n; i++)
{
k[i].p = k[i].b / k[i].a;
}
sort(k + 1, k + 1 + n, cmp);
double sum = 0.0;
for (int i = 1; i <= n; i++)
{
if (m >= k[i].a)
{
m = m - k[i].a;
sum += k[i].b;
}
else
{
sum += k[i].p * m;
break;
}
}
// cout << fixed << setprecision(2) << sum << endl; //c++保留小数一般表达
printf("%.2f\n", sum); //常用表达
system("pause");
return 0;
}
2.心得
熟悉algorithm内置函数,以及小数点保留使用。