“计算机程序设计能力考试(乙级)”真题刷题
二十六、题目:1026 程序运行时间 (15 分)
要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间。这个时间单位是 clock tick,即“时钟打点”。同时还有一个常数 CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数 f 的运行时间,我们只要在调用 f 之前先调用 clock(),获得一个时钟打点数 C1;在 f 执行完成后再调用 clock(),获得另一个时钟打点数 C2;两次获得的时钟打点数之差 (C2-C1) 就是 f 运行所消耗的时钟打点数,再除以常数 CLK_TCK,就得到了以秒为单位的运行时间。
这里不妨简单假设常数 CLK_TCK 为 100。现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。
输入格式:
输入在一行中顺序给出 2 个整数 C1 和 C2。注意两次获得的时钟打点数肯定不相同,即 C1 < C2,并且取值在 [0,10 7
]。
输出格式:
在一行中输出被测函数运行的时间。运行时间必须按照 hh:mm:ss(即2位的 时:分:秒)格式输出;不足 1 秒的时间四舍五入到秒。
输入样例:
123 4577973
输出样例:
12:42:59
1.代码
#include<iostream>
using namespace std;
int main() {
int c1, c2;
cin >> c1 >> c2;
int time = (c2 - c1 + 50) / 100;
int h, m, s;
s = time % 60;
h = time / 3600;
m = (time - 3600 * h) / 60;
printf("%02d:%02d:%02d", h, m, s);
return 0;
}
2.心得
**printf()**真的很实用呢,千万要熟悉使用
二十七、题目:1027 打印沙漏 (20 分)
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
、 *****
、 ***
、 *
、 ***
、*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
、*****
、 ***
、 *
、 ***
、*****
2
1.代码
妈耶,测试点2过不了,不知道哪里出错,来个大佬帮俺看一下吧~
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int n;
char c;
int i = 0; //记录需要构成三角形最小层次
cin >> n >> c;
int index = 0; //控制每行输出首个数时,前面需要空多少个空格。从0开始
int flat = 1; //处理首个有空格情况。1代表通过setw(index)输出每行的第一个,-1代表直接输出该行的剩余数
int sum = 0; //记录总共输出的c有多少个,如果不等于n就输出(n-sum)
while (1) {
//这里公式下面有给出解释
if (2 * i * i == n + 1)
break;
else if (2 * i * i > n + 1) {
i--; //大于就说明出现不足,i需要减去1再break才是满足的。这里就是为什么需要分开写
break;
}
i++;
}
//处理上三角
for (int j = i; j>0; j--) { //这里是逆序打印 7 5 3 1..
int t = 2*j-1; //每层的*都为奇数个,首项为1,通项公式为2n-1
while (t >0){ //while循环输出每层的*
if (flat ==1) {
index++; //index更新
cout << setw(index) << c;
sum++; //sum更新
}
else if (flat == -1) {
cout << c;
sum++;
}
flat = -1; //flat更新
t--;
}
cout << endl; //过段,进入下一层,重复过程
flat = 1; //flat更新
}
//处理下三角,同理跟上三角一样
for (int j = 1; j < i; j++) { //这里是顺序打印 3 5 7...
int t = 2 * j+1; //不同在这里,这里首项为3,所以通项公式为2n+1
while (t > 0) {
if (flat == 1) {
index--;
cout << setw(index) << c;
sum++;
}
else if (flat == -1) {
cout << c;
sum++;
}
flat = -1;
t--;
}
cout << endl;
flat = 1;
}
if (sum != n) //检查是否有剩余的数
cout << n - sum << endl;
system("pause");
return 0;
}
补充:公式的解释如下
2.心得
这道题蛮恶心的,格式化输出就是令人作恶。
二十八、题目:1028 人口普查 (20 分)
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数 N,取值在(0,105 ];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按
yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John
1.代码
#include <iostream>
#include <string.h>
using namespace std;
const char maxInputBirth[11] = "2014/09/06";
const char minInputBirth[11] = "1814/09/06";
int main() {
int n, count = 0;
char name[6], birth[11];
char maxName[6], minName[6];
char maxBirth[11] = "2014/09/06", minBirth[11] = "1814/09/06";
cin >> n;
while (n--) {
cin >> name >> birth;
if (strcmp(maxInputBirth, birth) >= 0 && strcmp(minInputBirth, birth) <= 0) {
count++;
if (strcmp(maxBirth, birth) > 0) {
strcpy(maxName, name);
strcpy(maxBirth, birth);
}
if (strcmp(minBirth, birth) < 0) {
strcpy(minName, name);
strcpy(minBirth, birth);
}
}
}
cout << count;
if (count > 0)
cout << " " << maxName << " " << minName;
return 0;
}
2.心得
咱也不知道为什么代码在Visul Studio运行不了,咱也不敢问。
二十九、题目:1029 旧键盘 (20 分)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字
0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
1.代码
#include<iostream>
#include<string.h>
using namespace std;
const int N = 200;
int s[N];
int main()
{
string a, b;
cin >> a;
cin >> b;
for (int i = 0; i < b.size(); i++)
{
s[b[i]]++;
}
for (int i = 0; i < a.size(); i++)
{
if (s[a[i]] == 0)
{
s[a[i]]++;
if (a[i] >= 'a' && a[i] <= 'z')
{
a[i] = a[i] - 32;
}
else if (a[i] >= 'A' && a[i] <= 'Z')
{
s[a[i] + 32]++;
}
s[a[i]]++;
cout << a[i];
}
}
system("pause");
return 0;
}
2.心得
注意大小写字母互换!!!
三十、题目:1030 完美数列 (25 分)
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105 )是输入的正整数的个数,p(≤109 )是给定的参数。第二行给出 N
个正整数,每个数不超过 109 。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
1.代码
测试点4过不了,妈耶,找不到,希望有个有缘人指出来,我TM直接跪下来感谢你。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
int main() {
long N, p;
cin >> N >> p;
vector<long> v;
long digit;
int count = 0;
for (int i = 0; i < N; i ++) {
cin >> digit;
v.push_back(digit);
}
sort(v.begin(), v.end()); //排好序,从小到大
reverse(v.begin(), v.end()); //翻转,变为从大到小
for (int i = 0; i < N; i++) {
if (v[0] > v[i]*p)
break;
count++;
}
cout << count;
system("pause");
return 0;
}
但是发现了一个老哥代码实现思路跟我差不多,但是还是看不出我哪里有问题。。。这是链接
他的代码:
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
long n,p;
cin>>n>>p;
long a[n];
int maxc=0;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int cnt=0;
for(int i=0;i<n;i++){
int j=cnt;
while(j++<n)
if(a[j]>a[i]*p)
break;
maxc=max(maxc,j-i);
cnt=j;
}
cout<<maxc<<endl;
return 0;
}
2.心得
本题不难,基本是平时经常遇到的题型,就是细节有问题,只能好好琢磨。。。