第D练——数学之美

第D练——数学之美

1. 数学之美 1.1. 水仙花数:Narcissistic.cpp(本题30分) 【题目描述】 输入整数n,输出第n小的“水仙花数”。所谓的“水仙花数”是指一个m位正整数,其各位数字的m次方之和等于该数本身。例如:8是一个“水仙花数”,因为8=81(8的一次方);153也是一个“水仙花数”,因为153=13+53+33(1的三次方+5的三次方+3的三次方)。

【程序分析】
利用while循环控制自1开始逐个正整数进行“水仙花数”测试。首先,获得数值的位数和各个数位上的数字。然后,进行是否为水仙花数的判断,若是则计数加1;否则进行下一个正整数的“水仙花数”测试。
循环此过程,直到找到第n个“水仙花数”。
【输入】
输入文件Narcissistic.in有1行,包含1个int类型的整数,即输入的变量n。
【输出】
输出文件Narcissistic.out有1行,包含1个int类型的整数,即第n个“水仙花数”。
【输入输出样例1】
Narcissistic.in Narcissistic.out
12 371
【输入输出样例2】
Narcissistic.in Narcissistic.out
18 92727
【数据限制】
1≤n≤20。

#include<stdio.h>

int digit[20]; //一个正整数的个、十、百、千、万……位上的数字字符

/*函数功能: 返回给定数值的位数(宽度),并将给定数值的个、十、百、千、万……位上的数字字符按 "低位到高位"的顺序从左到右存储在数组digit[.]中*/
int digitNum(int dn){
	//(1)返回给定数值的位数(宽度),并将给定数值的个、十、百、千、万……位上的数字字符存储在
	int w=0;//dn-给定的数字; w-给定的数字的位数(宽度)
	while( dn != 0 ){
		digit[w] = dn%10; //(A)获得[当前数值dn]的个位数
		
		w++; //(B)[原始数值dn]的位数(宽度)+1
		
		dn /=10; //(C)[当前数值dn]去除个位数
	}
	
	//(2)返回此数dn的位数(宽度)
	return w; 
}

/*函数功能: 求给定的数值num的n次方*/
int cifang(int num, int n){
	int result = num;
	for(int i=0; i<n-1; i++){
		result *= num;
	}
	return result;
}

int main() {
	int n, count = 0; //n-变量,表示想获得第n个水仙花数; count-目前找到的'水仙花数'的数目
	int i = 0; //i-循环变量,表示待测试的(正)整数
	int w; //w-数位宽度,表示整数i的数位宽度
	
	printf("请输入想获得的水仙花数的序号(n):");
	
	FILE *fp;
	if((fp=fopen("Narcissistic.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("Narcissistic.in", "r", stdin);
		freopen("Narcissistic.out", "w", stdout);
	}
	
	scanf("%d", &n); //输入想获得的水仙花数的序号
	//*************************************
	while(++i) { //for(i=100; i<1000; i++) {
		//(1)获得数值i的数位宽度w, 并将个、十、百、千、万……位上的数字字符按 "低位到高位"的顺序从左到右存储在数组digit[.]中
		w = digitNum(i);

		//(2)将数值i的w个数位上的数字分别进行w次方,并求和
		int sum = 0;
		for(int k=0; k<w; k++){
			//sum += power(digit[k], w); //数位digit[k]求w次方,并累加到总和sum中
			sum += cifang(digit[k], w); //数位digit[k]求w次方,并累加到总和sum中
		}
		
		//(3)若数值i的w个数位上数字的w次方的总和==(等于)i, 则为水仙花数! 并累加水仙花数 计数, 若已找到第n个,则输出,并退出循环
		if(i == sum){
			//(3.1)水仙花数的计数+1
			count++; 
			
			//(3.2)总共已经寻找到n个水仙花数,则输出次水仙花数, 并退出循环
			if(count == n){
				printf("%d", i); //第n个水仙花数-i
				break;
			}
		}
	}
	//=====================================
	return 0;
}

1.2. 完备数:PerfectNumber.cpp(本题30分) 【题目描述】 输入整数n,输出从小到大有序的第n个完备数及其因子信息。所谓的“完备数”是指一个数如果恰好等于它的因子之和,则这个数称为“完备数”。例如,6=1+2+3。

【程序分析】
利用while循环进行正整数遍历和退出条件控制;利用for循环进行某个整数的因子(整除数)搜索。
【输入】
输入文件PerfectNumber.in有1行,包含1个int类型的整数,即输入的变量n。
【输出】
输出文件PerfectNumber.out有1行,包含1个等式,即从小到大有序的第n个完备数及其因子信息。
【输入输出样例1】
PerfectNumber.in PerfectNumber.out
1 6=1+2+3
【输入输出样例2】
PerfectNumber.in PerfectNumber.out
2 28=1+2+4+7+14
【数据限制】
1≤n≤4。

#include<stdio.h>
int main(){
	int n, pefectCount, i; //n-完备数序号; pefectCount-完备数计数; i-遍历的循环变量
	int num, sum; //num-待测试是否为完备数的数值; sum-某个数num的因子和; 
	int factors[100]; //数num的因子
	int factorNum; //数num的因子个数
	
	printf("请输入待获得的完备数的序号(n):");

	FILE *fp;
	if((fp=fopen("PerfectNumber.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("PerfectNumber.in", "r", stdin);
		freopen("PerfectNumber.out", "w", stdout);
	}
	
	scanf("%d", &n);
	//********************************************
	//(1)初始化pefectCount和num
	pefectCount = 0; //完备数计数
	num = 1; //初始化待测试后的‘潜在完备数’(num从1开始...)

	//(2)num从1开始,测试后数值num是否为完备数?
	while(num++ && pefectCount < n){
		//(2.1)初始化sum和factorNum
		sum = 0; //初始化:因子的总和=0
		factorNum = 0; //初始化:因子的数目=0

		//(2.2)从1开始遍历(至num-1), 寻找num的因子
		for(i=1; i<num; i++){
			if(num%i == 0){//能整除,k是因子
				//(a)累加当前因子k
				sum += i;

				//(b)记录第factorNum个因子
				factors[factorNum] = i;
				
				//(c)因子个数factorNum+1
				factorNum++;
				
				//(d)如果数i的因子和已经超过数i自身,则直接跳过,不可能是完备数
				if( sum > num ){
					break;
				}
			}
		}
		
		//(2.3)如果num的因子之和sum恰好等于数num,则num为完备数
		if( sum == num ){
			pefectCount++; //
		}
		
		//(2.4)如果已经找到第n个完备数,则按要求输出该完备数的信息,并退出程序
		if(pefectCount == n){
			//(a)输出数值
			printf("%d=", num);
			
			//(b)输出所有因子
			for(i=0; i<factorNum-1; i++){
				printf("%d+", factors[i]);//输出因子信息
			}
			printf("%d", factors[factorNum-1]);
		}
	}
	//============================================
	return 0;
}

1.3. 回文数:Plalindrome.cpp(本题20分) 【题目描述】 输入整数n,判断整数n是否为回文数,是则输出YES,否则输出NO。例如,五位数12321是回文数,四位数1234不是回文数。

【程序分析】
学会分解出每一位数。
【输入】
输入文件Plalindrome.in有1行,包含1个long类型的整数,即输入的变量n。
【输出】
输出文件Plalindrome.out有1行,包含1个单词“YES”或“NO”,即是否为回文数。
【输入输出样例1】
Plalindrome.in Plalindrome.out
123454321 YES
【输入输出样例2】
Plalindrome.in Plalindrome.out
1690 NO
【数据限制】
1≤x≤1012。

#include<stdio.h>

int digit[50]; //一个正整数的个、十、百、千、万……位上的数字字符

/*函数功能: 返回给定数值的位数(宽度),并将给定数值的个、十、百、千、万……位上的数字字符按 "低位到高位"的顺序从左到右存储在数组digit[.]中*/
int digitNum(long dn){
	//(1)返回给定数值的位数(宽度),并将给定数值的个、十、百、千、万……位上的数字字符存储在
	int w=0;//dn-给定的数字; w-给定的数字的位数(宽度)
	
	//********************************************
	while( dn != 0 ){
		digit[w] = dn%10; //(A)获得[当前数值dn]的个位数

		w++; //(B)[原始数值dn]的位数(宽度)+1

		dn /=10; //(C)[当前数值dn]去除个位数
	}
	//============================================
	
	//(2)返回此数dn的位数(宽度)
	return w;
}

int main(){
	long n; //给定的整数
	int w; //w-数位宽度,表示整数n的数位宽度; 
	int i, flag; //i-判断是否回文时的循环变量;  flag-是否为回文数的标识(1-是, 0-否)
	printf("请输入待判断是否为回文数的正整数(n):");
		
	FILE *fp;
	if((fp=fopen("Plalindrome.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("Plalindrome.in", "r", stdin);
		freopen("Plalindrome.out", "w", stdout);
	}
	
	scanf("%ld", &n); //输入正整数n //scanf("%ld",&x);
	//********************************************
	//(1)初始化是否回文标识,默认将数n视为 回文!
	flag = 1;
	
	//(2)获得数值n的数位宽度w, 并将个、十、百、千、万……位上的数字字符按 "低位到高位"的顺序从左到右存储在数组digit[.]中
	w = digitNum(n);

	//(3)从数位两头往中间收缩,判断数字是否相同,一旦发现不同,则不是回文数
	for(i=0; (i<w) && (i<w-1-i); i++){
		if(digit[i] != digit[w-1-i]){//如果'两头(首-尾)'不相同,则不是回文数
			flag = 0;
			break;
		}
	}
	
	//(4)根据是否回文标识flag,按要求输出结果信息
	if(flag){//flag==1 是回文数
		printf("YES");
	}else{ //不是回文数
		printf("NO");
	}
	//============================================
	return 0;
}

1.4. 重复数:RegularNumber.cpp(本题20分) 【题目描述】 给定1-9之间的数字a和整数n,求和 (共有n个数相加)的值。例如,a=2,n=5时,和s=2+22+222+2222+22222=24690。

【程序分析】
解本题的关键是计算出每一项的值。
【输入】
输入文件RegularNumber.in有1行,包含2个数,第1个数是1-9之间的数字(即a),第2个数是一个整数(即n)。
【输出】
输出文件RegularNumber.out有1行,包含1个long类型的整数,即和s。
【输入输出样例1】
RegularNumber.in RegularNumber.out
2 5 24690
【输入输出样例2】
RegularNumber.in RegularNumber.out
5 8 61728390
【数据限制】
1≤a≤9,1≤n。

#include<stdio.h>

long sum(int a, int n){
	long int sn, tn; //sn-n个项的和;tn-某个项
	int count = 1; //count-表示累加了n项中的第count项

	//********************************************
	/**方法(一)*/
	sn = 0;
	tn = a;
	while(count <= n){
		//(A)累加当前项tn
		sn += tn;
		
		//(B)下一项
		tn = tn*10 + a;

		//(C)项数+1
		count++;
	}
	
	/**方法(二)
	sn = 0;
	tn = 0;
	while(count <= n){
		//(A)
		tn = tn + a;
		
		//(B)
		sn = sn + tn;

		//(C)
		a = a*10;
		
		//(D)项数+1
		++count;
	}
	*/
	//============================================
	
	//返回和sn
	return sn;
}

int main() {
	int a, n; //a-{1-9}之间的数字; n-和的项数(一个整数)
	long int s; //s-n项总和
	
	printf("请输入a和n的值:");

	FILE *fp;
	if((fp=fopen("RegularNumber.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("RegularNumber.in", "r", stdin);
		freopen("RegularNumber.out", "w", stdout);
	}
	
	scanf("%d%d", &a, &n); //输入a和n的值
	//printf("a=%d, n=%d!\n", a, n);
	//********************************************
	
	s = sum(a, n);		//调用函数sum获得n项和s
	
	//============================================
	printf("%ld", s); //输出n项和s //printf("a+aa+...=%ld\n", sn);
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值