第E练——数量处理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 222222337601
【输入输出样例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;
}