目录
1026 程序运行时间
1027 打印沙漏
1028 人口普查
1029 旧键盘
1030 完美数列
1026 程序运行时间
题目:
要获得一个 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
想法:
这题不用自己测试函数运行时间,其实题目讲的很清楚,按照题目说的去模拟即可
参考代码:
#include<stdio.h>
int main(){
int c1,c2;
scanf("%d%d",&c1,&c2);
float c3=c2-c1;
c3/=100;
int c4=0,t1=0,t2=0,t3=0; //(1)
if (c3-(int)c3>=0.5) c4=(int)c3+1; //(2)
else c4=(int)c3;
t1=c4/3600;
t2=(c4-t1*3600)/60;
t3=c4-t1*3600-t2*60;
printf("%02d:%02d:%02d",t1,t2,t3); //(3)
return 0;
}
(1)t1代表小时,t2代表分钟,t3代表秒
(2)四舍五入的判断
(3) 注意输出格式
1027 打印沙漏
题目:
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
***** *** * *** *****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
样例:
输入:
19 *输出:
*****
***
*
***
*****
2
想法:
先把要打印的行数一半算出,再将菱形分上下两半输出。
注意
不一定是输出 *,也可以是其他字符
参考代码:
#include<stdio.h>
#include<math.h>
int main(){
int n;
char a,b;
scanf("%d%c%c",&n,&b,&a);
int sum=(int)sqrt((n+1)/2); //(1)
int num=n-2*sum*sum+1; //(2)
for (int i=sum;i>0;i--){ //(3)
int j=2*i-1;
int k=(2*sum-1-j)/2;
while(k>0){
printf(" ");
k--;
}
while(j>0){
printf("%c",a); //(4)
j--;
}
printf("\n");
}
for (int i=2;i<=sum;i++){ //(5)
int j=2*i-1;
int k=(2*sum-1-j)/2;
while(k>0){
printf(" ");
k--;
}
while(j>0){
printf("%c",a);
j--;
}
printf("\n");
}
printf("%d",num);
return 0;
}
(1)2*(sum+1)^2-1=n,可以算出sum,即一半的行数
(2)因为行数是取整过的,所以用n去反减可以算出多余的字符数
(3)将菱形分上下部分打印
(4)打印的不一定是*,按它的输入为准
(5) 将菱形的下半部分输出
1028 人口普查
题目:
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 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
想法:
可以将年月日化为一个很大的整数,通过对整数的排序和比较来判断
参考代码:
#include<stdio.h>
#include<stdlib.h>
struct people{
char a[6];
/*int year;
int month;
int day;*/
int sum;
};
int cmp(const void *a,const void *b){
struct people *aa=(struct people*)a;
struct people *bb=(struct people*)b;
return ((aa->sum)-(bb->sum));
}
int main(){
int n;
scanf("%d",&n);
int num=n,k1=0,k2=0;
struct people town[n];
for (int i=0;i<n;i++){
char a1[11]={};
scanf("%s %s",town[i].a,a1);
int j=0;
town[i].sum=0;
while((a1[j]>=48 && a1[j]<=57) || a1[j]=='/'){
if (a1[j]>=48 && a1[j]<=57) town[i].sum=town[i].sum*10+(int)(a1[j]-48); //(1)
j++;
}
}
qsort(town,n,sizeof(town[0]),cmp); //(2)
int i=0;
while(i<n){
if ((20140906-town[i].sum)>2000000) num--; //(3)
else {
k1=i;
break;
}
i++;
}
i=n-1;
while(i>=0){
if (town[i].sum>20140906) num--; //(4)
else {
k2=i;
break;
}
i--;
}
if (num!=0) printf("%d %s %s",num,town[k1].a,town[k2].a);
else printf("0");
return 0;
}
(1)将年月日化为一个很大的整数
(2)排序
(3)超过两百岁生日的减去
(4) 未出生的减去
1029 旧键盘
题目:
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线
_
(代表空格)组成。题目保证 2 个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
样例:
输入:
7_This_is_a_test_hs_s_a_es
输出:
7TI
想法:
读入两个字符串,在字符串一中看哪个字符在字符串二没有
注意:
有可能某个字符在前面搜索时未出现,但在后面出现了,所以用了strchr函数
当字符串二搜完后,字符串一还没有搜完,需要将字符串一全部搜完才可以
参考代码:
#include<stdio.h>
#include<string.h>
int main(){
char message1[81]={};
char message2[81]={};
gets(message1);
gets(message2);
int len1=0;
len1=strlen(message1);
int i=0,j=0;
char a[81]={},c,*p2;
for (int i=0;i<len1;i++){
if (strchr(message2,message1[i])==NULL) { //(1)
if (message1[i]>=97) c=message1[i]-32; //(2)
else c=message1[i];
p2=strchr(a,c);
if (p2==NULL){ //(3)
a[j]=c;
j++;
}
}
}
for (int i=0;i<j;i++){
printf("%c",a[i]);
}
return 0;
}
(1)看该字符是否在字符串二中
(2)如果小写要变成大写
(3) 如果不在已找到坏键的数组中,才将其放入
1030 完美数列
题目:
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
样例:
输入:
10 82 3 20 4 5 1 6 7 8 9
输出:
8
想法:
从前往后找各个数的完美数列个数即可
注意
数组要赋初值0,不然过不了测试点4
必须要简化代码,不用每个数都遍历,不然测试点4会超时
参考代码:
#include<stdio.h>
#include<stdlib.h>
int cmp(const void*a,const void *b){
return *(int *)a-*(int *)b;
}
int main(){
long long n,p;
scanf("%lld%lld",&n,&p);
long long a[100001]={0}; //(1)
for (int i=0;i<n;i++) scanf("%d",&a[i]);
qsort(a,n,sizeof(long long),cmp); //(2)
int max=0,i=0,j=0;
for (;i<n;i++){
while(p*a[i]>=a[j] && j<n) j++; //(3)
if (j-i>max) max=j-i; //(4)
//if (j==n) break;
}
printf("%d",max);
return 0;
}
(1) 数组要赋初值,并且要开 long long
(2) 排序,注意sizeof里面是longlong
(3)从前往后找第一个比p*a[i]大的数
(4)比较是否比max大