PAT (Basic Level) Practice (中文)

1002 写出这个数

分数 20
作者 CHEN, Yue
单位 浙江大学
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

输入格式:
每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10
100

输出格式:
在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。

输入样例:
1234567890987654321123456789
输出样例:
yi san wu
**思考:**题目不难,我的问题在于用整形存储数时,当太大时,存储不了,所以可以用数组存储再计算

#include<stdlib.h>
#include<stdio.h>
#define LEN 1000
int main(){
	char n[LEN];
	int len=0,sum=0;
	for(int i=0;i<LEN;i++){
		scanf("%c",&n[i]);
		if(n[i]=='\n'){
			len=i;
			break;
		}
	}
	//求和 
	for(int i=0;i<len;i++){
		switch(n[i]){
				case '0':	sum+=0;break;
				case '1':	sum+=1;break;
				case '2':	sum+=2;break;
				case '3':	sum+=3;break;
				case '4':	sum+=4;break;
				case '5':	sum+=5;break;
				case '6':	sum+=6;break;
				case '7':	sum+=7;break;
				case '8':	sum+=8;break;
				case '9':	sum+=9;break;
			}
	}
	//得到和的每一位 
	int c[LEN],d[LEN],ll=0,jj=1; 
	for(int i=0;i<LEN;i++){
	c[i]=sum/jj%10;
	d[i]=sum/(jj*10);
	jj*=10;
	if(d[i]==0){
		ll=i;
		break;
	}
}
for(int i=ll;i>=0;i--){
			switch(c[i]){
				case 0:	printf("ling");break;
				case 1:	printf("yi");break;
				case 2:	printf("er");break;
				case 3:	printf("san");break;
				case 4:	printf("si");break;
				case 5:	printf("wu");break;
				case 6:	printf("liu");break;
				case 7:	printf("qi");break;
				case 8:	printf("ba");break;
				case 9:	printf("jiu");break;
			}
			if(i!=0)printf(" ");
		}
}

1004 成绩排名

分数 20
作者 CHEN, Yue
单位 浙江大学
读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。

输入格式:
每个测试输入包含 1 个测试用例,格式为

第 1 行:正整数 n
第 2 行:第 1 个学生的姓名 学号 成绩
第 3 行:第 2 个学生的姓名 学号 成绩
… … …
第 n+1 行:第 n 个学生的姓名 学号 成绩
其中姓名和学号均为不超过 10 个字符的字符串,成绩为 0 到 100 之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。

输出格式:
对每个测试用例输出 2 行,第 1 行是成绩最高学生的姓名和学号,第 2 行是成绩最低学生的姓名和学号,字符串间有 1 空格。

输入样例:
3
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
输出样例:
Mike CS991301
Joe Math990112
思考:题目不难,但是运行程序时总是结果不对,原因是数组长度没有留够,任何字符串末尾都会自动加上’\0’,'\0’是占一个位置的,所以如果一个长度为10的字符串要放在一个字符串数组里面的话,这个字符串数组长度至少为11

tips:字符串知识

https://blog.csdn.net/huhuhuhuhuhuha/article/details/124604724

#include<stdlib.h>
#include<stdio.h>

struct student{
	char name[20];
	char num[20];
	int score;
};

int main(){
	int n;
	scanf("%d",&n);
	getchar();
	struct student stu[1000];
//	input
	for(int i=0;i<n;i++){
		scanf("%s %s %d",stu[i].name,stu[i].num,&stu[i].score);
		getchar();
	}
	
//	judge
	int max=0,min=0;//成绩最高和最低的学生所在下标
	 for(int i=1;i<n;i++){
	 	if(stu[i].score>stu[max].score){
	 		max=i;
		 }
		 if(stu[i].score<stu[min].score){
	 		min=i;
		 }
	 }
	 printf("%s %s\n",stu[max].name,stu[max].num);
	printf("%s %s\n",stu[min].name,stu[min].num);	 
}

1005 继续(3n+1)猜想

分数 25
作者 CHEN, Yue
单位 浙江大学
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。

当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。

现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。

输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。

输出格式:
每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。

输入样例:
6
3 5 6 7 8 11
输出样例:
7 6
思考:本题重点在于思路,num[LEN]存储输入的数字,cpnum[LEN],输入数字的拷贝,status[LEN]判断是否为关键数,初始为1,a[LEN]存储验证过程中的数。
对num数组进行for循环,循环后会得到一串a[]验证过程中的数,把cpnum中的每个数都和a中的数比较,如果相等,就把status对应位置的值赋值为0,表明这个数被覆盖了。
for循环完后,status中的值全部更新完毕,拿到status中值为1对应的下标i,把cpnum[i]存到新数组prit中,再排序输出prit中的值。

#include<stdlib.h>
#include<stdio.h>
#define LEN 2000
struct number{
	int n;//存放输入的那个数字 
	int a[100];//存放 验证过程中的数字 
	int len;//a数组的长度  
};

int main(){
	int k;
	scanf("%d",&k);
	getchar();
	int num[LEN],cpnum[LEN],status[LEN],a[LEN]; //存输入;存输入的拷贝;表示是否是关键字,1为是;存验证过程中的数
	//input
	for(int i=0;i<k;i++){
		scanf("%d",&num[i]);
		cpnum[i]=num[i];
		status[i]=1;
	}
	for(int i=0;i<k;i++){
		int t=0,len=0;
		for(int ai=0;ai<LEN;ai++)a[ai]=0;
		
		if(status[i]==1){
			while(num[i]!=1){
			if(num[i]%2==0){
			num[i]/=2;
			a[t++]=num[i];
		}else{
			num[i]=(3*num[i]+1)/2;
			a[t++]=num[i];
		}
		}
		len=t; 
		
		//判断状态,不是关键数status为0 
		for(int j=0;j<k;j++){
			for(int m=0;m<len;m++){
				if(a[m]==cpnum[j]){
					status[j]=0;
				}
			}
		}
		} 
		
	}
	int chang=0,prit[LEN];
	for(int i=k-1;i>=0;i--){
			if(status[i]==1){
				prit[chang++]=cpnum[i];
			}
	
	}
	//排序
	for(int i=0;i<chang-1;i++){
		for(int j=i+1;j<chang;j++){
			if(prit[j]>prit[i]){
				int temp;
				temp=prit[i];
				prit[i]=prit[j];
				prit[j]=prit[i];
			}
		}
	} 
	//输出
	 for(int i=0;i<chang;i++){
	 	if(i==chang-1)printf("%d",prit[i]); 
	 	else printf("%d ",prit[i]); 
	 }
} 

1007 素数对猜想

在这里插入图片描述
输入格式:
输入在一行给出正整数N。
输出格式:
在一行中输出不超过N的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
思考:题目不难,主要思路是拿到小于n是素数数组,然后用for循环,判断相邻2个数差是否为2;提交代码后,有一个测试点过不了,提示段错误
在这里插入图片描述
检查之后发现把数字的大小设置小了,改大之后就好了,谨记:要根据题目条件给出的数字大小来设定数组大小,防止越界或溢出

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define LEN 100000
int issu(long int n){
	int is=1;
	if(n==2)return 1;
	else{
		int t=sqrt(n);
		for(long int i=2;i<=t;i++){
			if(n%i==0){
				is=0;
				break;
			}
		}
		return is;
	}
}

int main(){
	long int n;
	scanf("%ld",&n);
//	2 3 5 7 11 13 17 19
	long int index=0,a[LEN];
	for(long int i=2;i<=n;i++){
		if(issu(i)==1){
			a[index++]=i;
		}
	}
//	for(int i=0;i<index;i++)printf("%d ",a[i]);
	long int count=0;//满足猜想的对数 
	for(long int i=0;i<index-1;i++){
		if(a[i+1]-a[i]==2)count++; 
	}
	printf("%ld",count);
}

1009 说反话

分数 20
作者 CHEN, Yue
单位 浙江大学
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。

输出格式:
每个测试用例的输出占一行,输出倒序后的句子。

输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello
思考:本体重点在于处理连续多个空格;

#include<stdlib.h>
#include<stdio.h>

struct word {
	char c[100];
	int len;
};
int main() {
	struct word words[100];
	int wordlen = 0;//表示一共有多少个单词
	int flag = 0;//表示前一个字符是否为空格,0表示不是空格 
	char temp;//表示当前读入的字符
	for (int i = 0; i < 100; i++) {
		for (int j = 0; j < 100; j++) {
			while (1) {
				temp = getchar();
				if (temp == ' ' && flag == 1) {//当前字符为空格且前一个字符也是空格,说明是多个空格连续的情况,继续循环
					flag = 1;
				}
				else if (temp != ' ') {//当前字符不为空格,把flag更新,跳出循环
					flag = 0;
					break;
				}
				else if (temp == '\n') {//当前是换行,说明全部输入结束跳出while
					break;
				}
				else if (temp == ' ' && flag == 0) {//当前是空格且前一个不是空格,说明一个单词结束了,跳出while循环
					words[i].len = j;//得到一个单词的长度
					break;
				}
			}
			if (temp == ' ' && flag == 0) {//当前是空格且前一个不是空格,说明一个单词结束了,跳出一个for循环,为什么和27行代码一样的原因是,跳出while循环不能更新i,也就无法输入新单词,所以for循环也要跳出来

				break;
			}
			if (temp == '\n') {//当前是换行,说明全部输入结束跳出for循环,且可以得到单词的个数,就是i的值
				words[i].len = j;
				wordlen = i;
				break;
			}
			words[i].c[j] = temp;

		}
		if (wordlen != 0)break;//如果不判断wordlen的值,就无法跳出最外层for循环,就一直在输出状态

	}
	for (int i = wordlen; i >= 0; i--) {
		for (int j = 0; j < words[i].len; j++) {
			printf("%c", words[i].c[j]);
		}
		if (i != 0)printf(" ");
	}
}

1010 一元多项式求导

分数 25
作者 DS课程组
单位 浙江大学
设计函数求一元多项式的导数。(注:x
n
(n为整数)的一阶导数为nx
n−1
。)

输入格式:
以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。

输出格式:
以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0 0。

输入样例:
3 4 -5 2 6 1 -2 0
输出样例:
12 3 -10 1 6 0
思考:这道题输入我一直都有问题,scanf(“%d %d”,&xs[xsi],&zs[zsi])!=EOF这句话pta上可以正常运行,在dev上就不能正常运行,而是一直卡在循环。同时我的解法不完善。等有空了再思考一下

tips:附上EOF相关知识

链接

#include<stdlib.h>
#include<stdio.h>
#define LEN 10000

int main() {
	int xs[LEN], zs[LEN], len = 0;
	char c;
	int temp[LEN];
	int xsi = 0, zsi = 0;
	while (scanf("%d %d", &xs[xsi], &zs[zsi]) != EOF) {
		xsi++;
		zsi++;
	}



	for (int i = 0; i < xsi; i++) {
		if (zs[i] == 0) {
			xs[i] = 0;
		}
		else {
			xs[i] = xs[i] * zs[i];
			zs[i]--;
		}

	}
	for (int i = 0; i < xsi; i++) {

		printf("%d ", xs[i]);
		if (i == xsi - 1)printf("%d", zs[i]);
		else printf("%d ", zs[i]);
	}





}

1011 A+B 和 C

分数 15
作者 HOU, Qiming
单位 浙江大学
在这里插入图片描述

输入格式:
输入第 1 行给出正整数 T (≤10),是测试用例的个数。随后给出 T 组测试用例,每组占一行,顺序给出 A、B 和 C。整数间以空格分隔。

输出格式:
在这里插入图片描述

//输入样例:
4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647
//输出样例:
Case #1: false
Case #2: true
Case #3: true
Case #4: false

思考:题目不难,主要是输入要注意,因为题目给定的整数区间比较大,因此普通的int型不满足要求,要用long long int定义整数变量,在输入时要注意用%lld输入

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
struct num{
	long long int a;
	long long int b;
	long long int c;
	int count;
};

int main(){
	struct num nums[10];
	int t;
	scanf("%d",&t);
	for(int i=0;i<t;i++){
		scanf("%lld %lld %lld",&nums[i].a,&nums[i].b,&nums[i].c);
		nums[i].count=i+1;
	}
	for(int i=0;i<t;i++){
		if(nums[i].a+nums[i].b>nums[i].c)printf("Case #%d: true\n",nums[i].count);
		else printf("Case #%d: false\n",nums[i].count);
	}
}

1017 A除以B

分数 20
作者 CHEN, Yue
单位 浙江大学
本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。

输入格式:
输入在一行中依次给出 A 和 B,中间以 1 空格分隔。

输出格式:
在一行中依次输出 Q 和 R,中间以 1 空格分隔。

输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3
思考:本题涉及高精度的除法,相关信息如下链接,我自己的做法没有全部AC,有空再改

tips:高精度运算

高精度运算

#include<stdlib.h>
#include<stdio.h>

int main() {

	char a[1001];
	int b, r;
	scanf("%s %d", a, &b);
	int q[1001], len = 0;
	for (int i = 0; i < 1001; i++) {
		if (a[i] == '\0') {
			len = i;
			break;
		}
	}

	int temp = 0, trans = 0;
	int j = 0;//结果数组的下标 
	for (int i = 0; i < len; i++) { //101 5 =20..1
		trans = a[i] - '0';
		q[j++] = (temp * 10 + trans) / b;
		temp = (temp * 10 + trans) % b;
	}
	for (int i = 0; i < j; i++) {
		if (i == 0 && q[0] == 0) {

		}
		else {

			printf("%d", q[i]);
		}
	}
	printf(" %d", temp);
}

1020 月饼

分数 25
作者 CHEN, Yue
单位 浙江大学
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。

注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 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
思考:第一次提交不能完全AC,网上看别人的教程才知道自己有2个测试点没考虑到
1、输入的每种月饼的库存量和总售价,只是正数,而不是正整数,即可能含有小数部分。变量应该定义为float型,而不是int型。
2、有可能市场需求量大于所有种类月饼的库存量之和
考虑之后就能AC了

#include<stdlib.h>
#include<stdio.h>
//4.16 4.8 4.5 
struct yue {
	float sto;//库存 
	float total;//总价 
	float perprice;
	int tagg;//表示是否被访问过 
};
int main() {
	int n, d, sto[1001], price[1001];//n种类数,d最大需求量 
	float sum = 0;
	scanf("%d %d", &n, &d);
	int copyd = d;
	struct yue bing[1001];
	float zongliang = 0, zongjia = 0;
	for (int i = 0; i < n; i++) {
		scanf("%f", &bing[i].sto);
		zongliang += bing[i].sto;
	}
	for (int i = 0; i < n; i++) {
		scanf("%f", &bing[i].total);
		bing[i].tagg = 0;
		zongjia += bing[i].total;
	}
	if (zongliang <= d)printf("%.2f", zongjia);
	else {
		float perprice[1001];
		for (int i = 0; i < n; i++) {
			bing[i].perprice = bing[i].total * 1.0 / bing[i].sto;
		}

		float maxprice;//记录当前最大单价
		int maxindex[1001], maxi = 0;//存放当前最大单价下标 
		int j = 0, len = 0;
		while (1) {
			maxprice = -1;
			for (int i = 0; i < n; i++) {
				if (bing[i].perprice >= maxprice && bing[i].tagg == 0) {
					maxprice = bing[i].perprice;
					maxi = i;
				}
			}
			maxindex[j++] = maxi;
			bing[maxi].tagg = 1;
			len++;
			if (bing[maxi].sto >= d) {
				break;
			}
			else {
				sum += bing[maxi].total;
				d -= bing[maxi].sto;

			}
		}
		sum += d * bing[maxi].perprice;
		printf("%.2f", sum);
	}


}

1022 D进制的A+B

在这里插入图片描述

输入格式:
输入在一行中依次给出 3 个整数 A、B 和 D。
输出格式:
输出 A+B 的 D 进制数。
输入样例:
123 456 8
输出样例:
1103
思路:借助10进制转换成2进制的思路,除2取余法,要注意和为0的情况,输出的时候要颠倒过来输出

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define LEN 100;
main(){
	int a,b,d;
	scanf("%d %d %d",&a,&b,&d);
	int sum=a+b;
	int temp;
	int res[1000],t=0;
    if(sum==0){
        printf("0");
    }else{
        while(sum!=0){
		temp=sum%d;
		res[t++]=temp;
		sum/=d;
	}
	for(int i=t-1;i>=0;i--){
		printf("%d",res[i]);
	}
    }
	
}

1026 程序运行时间
在这里插入图片描述
在这里插入图片描述

思路:思路简单,先把小时算出来,再算分,再算秒,需要注意的地方一个是四舍五入,一个是时分秒都要是整数,注意不要用小数除

tips:四舍五入的方法

https://blog.csdn.net/m0_72482689/article/details/125997219

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>

int main(){
	double c1,c2;
	long long int CLK_TCK =100;
	scanf("%lf %lf",&c1,&c2);
	double cha;
	cha=(c2-c1)*1.0/CLK_TCK;
	cha=round(cha);
	
	int h,m,s;
	h=cha/3600;
	m=(cha-h*3600)/60;
	s=cha-h*3600-60*m;
	printf("%02d:%02d:%02d",h,m,s);
}

tips:C语言常用函数:

https://zhuanlan.zhihu.com/p/451192455

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值