PAT-BASIC 1026-1030

本文探讨了如何测量C语言程序的运行时间,通过使用time.h库中的clock()函数和CLK_TCK常数实现。此外,还介绍了一个算法问题,即如何从一组正整数中选择尽可能多的数构成完美数列,其中数列的最大值不超过最小值的p次方。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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,107]。

输出格式:

在一行中输出被测函数运行的时间。运行时间必须按照 hh:mm:ss(即2位的 时:分:秒)格式输出;不足 1 秒的时间四舍五入到秒。

输入样例:

123 4577973         

输出样例:

12:42:59

分析

如果c不加50会有一个测试点错误,应该是为了四舍五入

Code

#include<iostream>

using namespace std;

int main(){
	int c1,c2;
	cin>>c1>>c2;
	int c=c2-c1;
	int n=(c+50)/100;
	int hh=n/60/60;
	int mm=(n%3600)/60;
	int ss=(n%3600)%60;
	printf("%02d:%02d:%02d", hh, mm, ss);
	return 0;
}

1027 打印沙漏 (20分)

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

      
    

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:

19 *          

输出样例:

*****
 ***
  *
 ***
*****
2

分析

本题的难点在于找到规律 从中间开始 3 5 7每行+2 +…+(2i+1)=(3+2i+1)i/2 = i(i+2)

所以一个沙漏需要1+2*i(i+2)

Code

#include <iostream>
using namespace std;
int main() {
	int n,row=0;
	char c;
	cin>>n>>c;
	for(int i=0; i<n; i++) {
		if((2*i*(i+2)+1)>n) {
			row=i-1;
			break;
		}
	}
	for (int i = row; i >= 1; i--) {
		for (int k = row - i; k >= 1; k--) cout << " ";
		for (int j = i * 2 + 1; j >= 1; j--) cout << c;
		cout << endl;
	}
	for (int i = 0; i < row; i++) cout << " ";
	cout << c << endl;
	for (int i = 1; i <= row; i++) {
		for (int k = row - i; k >= 1; k--) cout << " ";
		for (int j = i * 2 + 1; j >= 1; j--) cout << c;
		cout << endl;
	}
	cout << (n - (2 * row * (row + 2) + 1));
	return 0;
}

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

分析

本想根据输入一个个比较 比如前四位是否大于2014 后来发现输入的birth可以直接和maxbirth比较 省了很多事,这就是string 的好处吧

Code

#include <iostream>
using namespace std;
int main() {
	int n, count = 0;
	cin >> n;
	string name, birth, maxname, minname, maxbirth = "1814/09/06", minbirth =
	            "2014/09/06";
	for (int i = 0; i < n; i++) {
		cin >> name >> birth;
		if (birth >= "1814/09/06" && birth <= "2014/09/06") {
			count++;
			if (birth >= maxbirth) {
				maxbirth = birth;
				maxname = name;
			}
			if (birth <= minbirth) {
				minbirth = birth;
				minname = name;
			}
		}
	}
	cout << count;
	if (count != 0) cout << " " << minname << " " << maxname;
	return 0;
}

1029 旧键盘 (20分)

旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。

输入格式:

输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。

输出格式:

按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。

输入样例:

7_This_is_a_test
_hs_s_a_es        

输出样例:

7TI

Code

对每个字符进行存储和处理

#include<bits/stdc++.h>
using namespace std;
int main()
{
	
	string a,b;
	cin>>a>>b;
	int s[200]={0};
	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];
		}
	}
	return 0;
} 

更好的版本,更简单明了

其中string:npos是个特殊值,说明查找没有匹配

#include <iostream>
#include <cctype>
using namespace std;
int main() {
	string s1, s2, ans;
	cin >> s1 >> s2;
	for (int i = 0; i < s1.length(); i++)
		if (s2.find(s1[i]) == string::npos && ans.find(toupper(s1[i])) ==
		        string::npos)
			ans += toupper(s1[i]);
	cout << ans;
	return 0;
}

1030 完美数列 (25分)

给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 Mm**p,则称这个数列是完美数列。

现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数 Np,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

输入样例:

10 8
2 3 20 4 5 1 6 7 8 9     

输出样例:

8

Code

存在运行超时错误 只有22分,一个测试点没过,得优化下

#include<iostream>
#include <vector>
#include<algorithm>
using namespace std;

int main(){
	int N;
	long long p;
	cin>>N>>p;
	vector<int> v(N);
	for(int i=0;i<N;i++){
		cin>>v[i];
	}
	sort(v.begin(),v.end());
	int num=0,maxnum=0;
	for(int i=0;i<N;i++){
		for(int j=N-1;j>=0;j--){
			if(v[i]*p>=v[j]) {
				num=j-i+1;
				if(num>maxnum) maxnum=num;
				break;
			}
		}
	}
	cout<<maxnum;
}

优化后:

上段代码的maxnum计算 每次从0开始循环,改后只能越来越大

同时注意p是long long类型不然int*int可能会溢出段错误

#include<iostream>
#include <vector>
#include<algorithm>
using namespace std;

int main(){
	int N;
	long long p;
	cin>>N>>p;
	vector<int> v(N);
	for(int i=0;i<N;i++){
		cin>>v[i];
	}
	sort(v.begin(),v.end());
	int maxnum=0;
	for(int i=0;i<N;i++){
		for(int j=i+maxnum;j<N;j++){
			if(v[i]*p>=v[j]) {
				maxnum=j-i+1;
			}
			else break;
		}
	}
	cout<<maxnum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值