PTA日常训练(C语言详细版)

1.找完数

所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。本题要求编写程序,找出任意两正整数m和n之间的所有完数。

输入格式:

输入在一行中给出2个正整数m和n(1<m≤n≤10000),中间以空格分隔。

输出格式:

逐行输出给定范围内每个完数的因子累加形式的分解式,每个完数占一行,格式为“完数 = 因子1 + 因子2 + ... + 因子k”,其中完数和因子均按递增顺序给出。若区间内没有完数,则输出“None”。

输入样例:

2 30

输出样例:

6 = 1 + 2 + 3
28 = 1 + 2 + 4 + 7 + 14

解题代码:

#include <stdio.h>

int main() {
    int m, n, sum;
    int i, j;
    int count = 0;
    scanf("%d %d", &m, &n);
    for (i = m;i <= n;i++) {
        //这里控制的是题目上給的从n到m个数字,注意输入和输出格式
        if (i == 1) {
            continue;
            //一不是完数,如果是有一的话直接跳过一
        }
        sum = 1;//sum计算因数的和,它至少有一个1,所以sum从1开始
        for (j = 2;j < i;j++) {
            if (i % j == 0) {
                //计算因数,如果是取余为0,那么就是因数
                sum = sum + j;
                //将每次的因数加起来求和
            }
        }
            //要判断这个数是不是完数,要是你的因数和等于自己的大小,那么你1就是完数
            if (i == sum) { //是完数
                printf("%d = 1", i);
                for (j = 2;j < i;j++) {
                    if (i % j == 0) {
                        printf(" + %d", j);
                    }
                }
                printf("\n");
                count++;
            }

    }
    //count用来统计有几个完数
    if (count == 0) {
        printf("None\n");
    }
    return 0;
}

 2.水仙花数

输入两个3位的正整数m,n,输出[m,n]区间内所有的“水仙花数”。所谓“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身。

输入格式:

测试数据由多组,处理到文件尾。每组测试输入两个3位的正整数m,n(100≤m<n≤999)。

输出格式:

对于每组测试,若[m,n]区间内没有水仙花数则输出“none”(引号不必输出),否则逐行输出区间内所有的水仙花数,每行输出的格式具体参看输出样例。

输入样例:

100 150
100 200

输出样例:

none
153=1*1*1+5*5*5+3*3*3

解题代码:

#include<stdio.h>
#include<math.h>//方便计算后边的立方,也可以自己写一个立方函数,比较简单
//pow(x,y)函数,x的y次幂
/*
思路:
1.将每一位的数字单独摘出来
2.判断是否是完数
注意:他是在一个范围之内,所以要用一个循环来控制变量
注意输入输出格式,它这个是一次要输入多组数据,要是在c++中可以用vector动态申请一个动态二维数组
这里我们加一个循环来模拟控制一波
*/
int main() {
	int m, n;//给了两个变量来接收范围
	int i;  //循环变量
	int sum;//用来判断每个项的立方和
	int b, s, g;//定义三个变量分别表示百位,十位,个位;
	int count = 0;//用来计数
	while (scanf("%d %d", &m, &n) != EOF) {
		//EOF解释;EOF在c语言中表示文本资料的结束,大家可以联想一下我们讲文件的时候判断文件那一块哦
		for (i = m;i <= n;i++) {
			//将百、十、个位都摘出来
			b = i / 100;
			s = i / 10 % 10;
			g = i % 10;
			sum = pow(b, 3) + pow(s, 3) + pow(g, 3);//计算平方和
			//进行比较,判断是否是水仙花
			if (sum == i) {
				printf("%d=%d*%d*%d+%d*%d*%d+%d*%d*%d\n", i, b, b, b, s, s, s, g, g, g);
				count++;//每次有一个水仙花,计数器就加易
			}
		}

		if (count == 0) {
			printf("none\n");
		}

	}


	return 0;
}

 3.单词长度

你的程序要读入一行文本,其中以空格分隔为若干个单词,以.结束。你要输出每个单词的长度。这里的单词与语言无关,可以包括各种符号,比如it's算一个单词,长度为4。注意,行中可能出现连续的空格;最后的.不计算在内。

输入格式:

输入在一行中给出一行文本,以.结束

提示:scanf("%c",...);来读入一个字符,直到读到.为止。

输出格式:

在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行末没有最后的空格。

输入样例:

It's great to see you here.

输出样例:

4 5 2 3 3 4
#include<stdio.h>

/*
使用while(scanf)会运行时间超
思路:每个单词之间是靠空格来隔开,文本结束时候是个‘.’所以在计数的时候结束标志就是一个空格或者一个‘.’
根据提示可以得到输入的格式
我的思路是每次判断,有些人可能会用一个数组将所有的字符都保存起来,这里没有给范围,我感觉有点麻烦
1.一开始我是使用一个while将每次输入进来  while (scanf_s("%c", &c)!='.'),然后超时了,而且最后一个和'.'相连的单词会少算一个字母
所以使用分开输入,采用do while格式
2.判断计数结束,两种情况
这个题要注意多种情况:空句子、有多个连续的空格,只有一个单词,开头和结尾有多个空格
最大的坑是输出格式,第一个的出书格式与其他的不同,所以将他做个标记分开输出
*/
int main() {
    char c;//我用的是每次判断
    int count = 0;//用来判断一个单词有几个字符
    //分开接受字符
    int first = 0;//用来记录第一个单词
    do {
        scanf("%c", &c);
        if (c != ' ' && c != '.') {
            count++;               //计数器,用来计算单词中字母的个数
        }
        else {
            //这种情况就是遇到了空格或者'.'停止计数
            if (first == 0 && count != 0) {
                //这种情况代表第一个单词的情况
                printf("%d", count);
                first = 1;//修改判断条件,第一个单词已经输出了
            }
            else if (count != 0) {
                printf(" %d", count);
            }
            count = 0;
        }
    } while (c != '.');
    return 0;
}


 

4.猜数字

一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。

输入格式:

输入在第一行给出一个正整数N(≤104)。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。

输出格式:

在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。

输入样例:

7
Bob 35
Amy 28
James 98
Alice 11
Jack 45
Smith 33
Chris 62

输出样例:

22 Amy
#include<stdio.h>
#include<math.h>
/*
* 首先看这个题的要求,就是计算平均数,然后找最接近的那个,然后将平均数的一半输出 加 这个人的名字
* 注意数字直接用整形就行
思路:
我的思路是:
1.用一个结构体将他的名字和它的数字保存起来
2.拿到所有数字并且求平均值
3.进行比较,比较差的绝对值的大小,绝对值越小的就是要找的节点
4.输出(注意格式)
*/



typedef struct people{
	char name[10];//c语言中没有string类型的变量,
    //所以用个数组来代替一下,名字的长度最多为8,一开始用8,答案部分正确,改成10,还是段错误
	int num;
}s;


#define max 100000   //最多有100名玩家,别管,我猜的,过不去就再加,然后就真的不对了,段错误,
//之后逐次加0,直到对,毕竟数组就俩,不是上边那个就是下边这个
int main() {
	s player[max]; //初始化100个玩家,就要有100个结构体,先开辟空间再说
	int N;//有N名玩家
	int i;
	double avg,sum=0;//代表一开始计算的平均数,为了精确使用double
	int simavg;//代表最后要输出的一半的平均数
	scanf("%d", &N);
	for (i = 0;i < N;i++) {
		scanf("%s %d", player[i].name, &player[i].num);
		sum += player[i].num;
		//这一步结束我们就拿到了所有的信息
	}
	//计算平均数
	avg = sum / N;
    simavg = (int)avg / 2;
	//每个数字与平均数的一半的差的绝对值进行比较,方法类似冒泡排序,有人比他小就换位置
	//假设第一个是最小的

	s min = player[0];
	for (i = 1;i < N;i++) {
		if (fabs(player[i].num - simavg) < fabs(min.num - simavg)) {
			//s temp ;
			//temp = min;
			min = player[i];
			//player[i] = temp;
			交换两个结构体
		}
	}
	//循环结束后,最小的就是第一个啦
	
	printf("%d %s", simavg, min.name);
	return 0;
}

5.连续因子 

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。

输入格式:

输入在一行中给出一个正整数 N(1<N<231)。

输出格式:

首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。

输入样例:

630

输出样例:

3
5*6*7

 

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

/*
思路:
这个题就是一个变形的阶乘
先判断是否否和,再返回去求长度
*/


int main() {
	int i, j;
	int N;//输入的正正数
	int  sum;//用来保存累乘的结果
	int len = 0;//用来记录长度
	int start = 0;//做好记录,要记录最先开始的那个元素,方便之后进行输出
	//累乘只需要到根号N,这样时间复杂度只是logN;因为当数字大于根号N
	//的时候肯定还有一个数字大于根号N,导致积大于根号N。
	scanf("%d", &N);
	for (i = 2;i <= sqrt(N)+1;i++) {
		//控制第一个起点
		sum = 1;
		for (j = i;j <= sqrt(N)+1;j++) {//控制从i个数字之后的阶乘
			sum *= j;
			if (N % sum == 0) {
				//要判断是否是最长的那个序列,如果不是要做一个更新
				if (j - i + 1 > len) {
					//这里为啥是j-i+1就是因为这个是从i开始阶乘,到j结束的一个长度
					len = j - i + 1;//做好更新
					start = i;
				}
			}
			else break;//如果阶乘出现了不为0的情况直接退出这次循环,因为如果一个数字被2*3*4整除,那么他也可以被2*3整除
		}
	}
	if (start != 0) {//说明一个都没找到
		printf("%d\n", len);
		printf("%d", start);
		for (i = start + 1;i < start + len;i++) {
			printf("*%d", i);	
	}
    }
	else {//有多个,输出最长的len和从start开始的序列
	   start = N;//只有从N开始一个长度了
		len = 1;
		printf("%d\n", len);
		printf("%d", N);
		}

	return 0;
}

6.A除以B(PTA) 

真的是简单题哈 —— 给定两个绝对值不超过100的整数A和B,要求你按照“A/B=商”的格式输出结果。

输入格式:

输入在第一行给出两个整数A和B(−100≤A,B≤100),数字间以空格分隔。

输出格式:

在一行中输出结果:如果分母是正数,则输出“A/B=商”;如果分母是负数,则要用括号把分母括起来输出;如果分母为零,则输出的商应为Error。输出的商应保留小数点后2位。

输入样例1:

-1 2

输出样例1:

-1/2=-0.50

输入样例2:

1 -3

输出样例2:

1/(-3)=-0.33

输入样例3:

5 0

输出样例3:

5/0=Error
#include<stdio.h>




/*
思路:
本题的关键是输出的格式与输入的变量类型
输入的是有符号整形    int
输出的是有符号类型的浮点类型,并且保存小数点后两位  float
1.判断分母是否为0(就是除数)如果为0,就要上一个括号,分母为0就输出Error

*/

int main() {
	int A, B;
	float sum;//
	scanf("%d %d",&A,&B);//这里定义两个变量
	sum = (float)A / B;
	if (B == 0) {
		printf("%d/%d=Error",A,B);
	}
	else if (B < 0) {
		printf("%d/(%d)=%.2f",A,B,sum);
	}
	else {
		printf("%d/%d=%.2f", A, B, sum);
	}

	return 0;
}