第E练——数量处理1

第E练——数量处理1

  1. 数量处理

1.1. 最大公约数和最小公倍数:DivisorMultiple.cpp(本题15分) 【题目描述】 输入两个正整数m和n,求其最大公约数和最小公倍数。

【程序分析】
利用辗除法。
【输入】
输入文件DivisorMultiple.in有1行,包含2个int类型的整数,即输入的变量m和n。
【输出】
输出文件DivisorMultiple.out有1行,包含2个int型整数,即整数m和n的最大公约数和最小公倍数,两个整数之间由1个空格隔开。
【输入输出样例1】
DivisorMultiple.in DivisorMultiple.out
75 25 25 75
【输入输出样例2】
DivisorMultiple.in DivisorMultiple.out
24 72 24 72
【数据限制】
m≥1,n≥1。

#include<stdio.h>
int main() {
	int num1, num2, a, b, temp; //num1, num2-两个待处理的正整数; a,b-辗转相除时用的变量; temp-临时变量
	printf("请输入两个整数(num1&num2):\n");

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

		freopen("DivisorMultiple.in", "r", stdin);
		freopen("DivisorMultiple.out", "w", stdout);
	}
	
	scanf("%d%d", &num1, &num2);
	//printf("%d, %d\n", num1, num2);
	//************************************
	//(1)确保 num1>=num2
	if(num1 < num2) {
		temp = num1;
		num1 = num2;
		num2 = temp;
	}

	//(2)不改变num1和num2的值,进行辗转相除
	a = num1;
	b = num2;
	while(b != 0){ /*利用辗除法,直到b为0为止*/
		temp = a%b;
		a = b;
		b = temp;
	}
	
	//(3)输出最大公约数a和最小公倍数(num1*num2/a)
	printf("%d %d", a, num1*num2/a);//printf("最大公约数:%d, 最小公倍数:%d\n", a, num1*num2/a);
	//=====================================
	return 0;
}

1.2. 正整数分解质因数:PrimeFactors.cpp(本题15分) 【题目描述】 将一个正整数分解质因数。例如:输入90,打印出233*5。

【程序分析】
对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:
(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印输出即可。
(2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
【输入】
输入文件PrimeFactors.in有1行,包含1个int类型的整数,即输入的变量n。
【输出】
输出文件PrimeFactors.out有1行,包含1个整数乘式,即整数n的质分解,例如2335。
【输入输出样例1】
PrimeFactors.in PrimeFactors.out
2423232 2
22222337601
【输入输出样例2】
PrimeFactors.in PrimeFactors.out
123123 37111341
【数据限制】
n≥1。

#include<stdio.h>
int main() {
	int n, i; //n-待分解的整数; i-循环变量
	printf("请输入待分解的正整数(n):\n");

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

		freopen("PrimeFactors.in", "r", stdin);
		freopen("PrimeFactors.out", "w", stdout);
	}
	
	scanf("%d", &n); //输入待质分解的正整数
	//printf("%d=", n);
	//******************************************
	//(1)从2开始,寻找整数n的因子(每个因子循环 判断,是否为因子?)
	for(i=2; i<=n; i++){
		while(n != i){ //i恰等于n,则说明分解质因数的过程已经结束
			if(n%i == 0){ //整数n能够被i整除,即i是n的因子
				printf("%d*", i);
				n = n/i;
			} else{
				break;
			}
		}
	}
	printf("%d", n);
	//=====================================
	return 0;
}

1.3. 数列和:SeriesSUM.cpp(本题20分) 【题目描述】 给定整数n,求分数序列:2/1,3/2,5/3,8/5,13/8,21/13,……前n项之和。

【程序分析】
请抓住分子与分母的变化规律。
【输入】
输入文件SeriesSUM.in有1行,包含1个int类型的整数,即输入的变量n。
【输出】
输出文件SeriesSUM.out有1行,包含1个保留6位小数的double类型的浮点数,即输出的序列和。
【输入输出样例1】
SeriesSUM.in SeriesSUM.out
20 32.660261
【输入输出样例2】
SeriesSUM.in SeriesSUM.out
8 13.243746
【数据限制】
1≤n≤100。

#include<stdio.h>
int main(){
	int n, i; //n-序列的项数; i-循环变量; 
	double a, b, t, s; //a, b-项的分子&分母; t-临时变量; s-序列的和
	
	printf("请输入待计算的序列的项数(n):\n");
	
	FILE *fp;
	if((fp=fopen("SeriesSUM.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("SeriesSUM.in", "r", stdin);
		freopen("SeriesSUM.out", "w", stdout);
	}
	
	scanf("%d", &n); //序列项数n
	//********************************************
	//(1)初始化第一项的分子a&分母b及和s。
	a = 2;
	b = 1;
	s = 0;
	
	//(2)循环,进行"项"累加
	for(i=1; i<=n; i++){
		//(2.1)累加项:a/b
		s = s + a/b;
		
		//(2.2)更新下一项的a & b  /*这部分是程序的关键,请读者猜猜t的作用*/
		t = a;
		a = a + b;
		b = t; 
	}
	
	//(3)打印输出序列的和,有效小数6位
	printf("%.6f", s);
	//============================================
	return 0;
}

1.4. 兔子问题:Rabit.cpp(本题10分) 【题目描述】 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第n个月的兔子总数为多少(n为一个正整数)?

【程序分析】
古典问题:兔子的规律为数列1,1,2,3,5,8,13,21,……。
【输入】
输入文件Rabit.in有1行,包含1个int类型的整数,即输入的变量n(月份)。
【输出】
输出文件Rabit.out有1行,包含1个int类型的整数,即第n个月的兔子总数。
【输入输出样例1】
Rabit.in Rabit.out
1 1
【输入输出样例2】
Rabit.in Rabit.out
8 21
【数据限制】
1≤n≤40。

#include<stdio.h>

int main(){
	long rabitNum; //第n个月的兔子数目
	long f1, f2, temp; //f1,f2-序列的连续2项; temp-临时变量
	int n, i; //n-月份; i-循环变量
	
	printf("请输入待计算的月份(n):");
	
	FILE *fp;
	if((fp=fopen("Rabit.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("Rabit.in", "r", stdin);
		freopen("Rabit.out", "w", stdout);
	}

	scanf("%d", &n); //月份n
	//********************************************
	//(1)初始化序列的头2项: f1,f2
	f1 = 1;
	f2 = 1;
	
	//(2)获得: 第1月 & 第n(n>=2)月兔子总数
	if(n == 1){//第1个月的兔子总数
		rabitNum = f1; //输出第1个月的兔子数目
	//}else if(n == 2){//第2个月的兔子总数
	//	rabitNum = f2; //输出第1个月的兔子数目
	}else{//循环求取第n(>2)个月的兔子总数
		for(i=3; i<=n; i++) {
			temp = f1 + f2;
			f1 = f2;
			f2 = temp;

			/**
			printf("%12ld %12ld", f1, f2);
			if(i%2 == 0){
				printf("\n");//控制输出,每行四个
			}
			f1 = f1+f2; //前两个月加起来赋值给第三个月
			f2 = f1+f2; //前两个月加起来赋值给第三个月
			*/
		}
		
		rabitNum = f2; //输出第n个月的兔子数目
	}
	
	//(3)输出第n个月的兔子数目
	printf("%ld", f2);//输出第n个月的兔子数目
	//=====================================
	return 0;
}

1.5. 猴子分桃:DividePeach.cpp(本题40分) 【题目描述】 海滩上有一堆桃子,由n只猴子来分。第一只猴子把这堆桃子凭据分为n份,多了一个,这只猴子把多的一个扔入海中,拿走了一份。第二只猴子把剩下的桃子又平均分成n份,又多了一个,它同样把多的一个扔入海中,拿走了一份。第三、第四、第五、第n只猴子都是这样做的,问海滩上原来最少有多少个桃子?

【程序分析】
满足条件的桃子数目可能有多个,本题的目标是寻找满足条件的最少桃子数目。
桃子的数目采用枚举(循环)测试,猴子分桃的过程采用“递归”进行模拟。
【输入】
输入文件DividePeach.in有1行,包含1个int类型的整数,即猴子的数目n。
【输出】
输出文件DividePeach.out有1行,包含1个int类型的整数,即海滩上桃子的数目。
【输入输出样例1】
DividePeach.in DividePeach.out
3 25
【输入输出样例2】
DividePeach.in DividePeach.out
5 3121
【数据限制】
3≤n≤8。

#include <stdio.h>
/*注意:注释以n=5为例进行说明!*/
int main(){
	int n; //猴子的数目
	int peachNum; //桃子的数目->从后向前进行[枚举]&[递推]时看到的桃子的数目
	int monkeyID; //猴子编号ID,用于[从后向前枚举时]标识目前拿桃子的猴子(第monkeyID只猴子)

	int i; //循环变量,表示最后1只[第n只]猴子(吃1个+拿走1/5后)看到的桃子的数目, 因剩下4/5(4份)-因此此数必然为4的倍数!
	
	printf("请输入猴子的数目(n):");
	
	FILE *fp;
	if((fp=fopen("DividePeach.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("DividePeach.in", "r", stdin);
		freopen("DividePeach.out", "w", stdout);
	}
	
	scanf("%d", &n); //猴子的数目n
	
	//解题方法:从最后1只[第n只]猴子(吃1个+拿走1/5后)看到的桃子的数目开始,从后向前进行‘逆向’[枚举]&[递推]!
	for(i=(n-1);  ; i+=(n-1)){//死循环
		//********************************************
		//(A)初始时刻:最后1只拿走桃子的猴子的ID为(monkeyID=n;)
		monkeyID = n; // monkeyID = 5; //

		//(B)初始时刻:最后1只猴子(吃1个+拿走1/5后)看到的桃子的数目(peachNum=i;)
		peachNum = i;
		
		//(C)从最后1只猴子(ID=monkeyID)开始,从后向前进行枚举,...
		while(monkeyID-- > 0){//for(k=5; k>=1; k--){//
			//(C.1)第monkeyID只猴子[吃+拿之前]看到的桃子数目
			peachNum = (peachNum/(n-1))*n + 1; //peachNum = (peachNum/4)*5 + 1;

			//(C.2)若第monkeyID只猴子[吃+拿之前]看到的桃子数目-->不是4的倍数则不符合要求! 因为上一只猴子拿剩4/5!
			if(peachNum%(n-1) != 0){
				break; //退出[内]循环-->n只猴子[吃+拿]桃子‘逆’过程模拟
			}
		}
		
		//(D)若程序执行到此,可能出现2情况: (1)n只猴子[吃1+拿1/5]的整个过程枚举完成;(2)某只猴子[吃1+拿1/5后]桃子剩余数目i不合理!
		if(monkeyID == 0){//从后向前进行‘逆向’[枚举]&[递推]过了第1只(monkeyID==0)猴子-->枚举过程结束
			printf("%d\n", peachNum);
			break;
		}
		//=====================================
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值