【6.1】连续整数固定和问题:找出任意输入的整数n的全部的连续整数固定和。
题目分析: 至少要找出两个连续整数的固定和,一个整数的话就是本身了呢。那如何确定这些连续整数呢?想明白了,第一个整数设为a,第二个整数是a+1,…,假设有m个连续整数,那么第m个整数是a+(m-1),这m个整数的和是ma+m*(m-1)/2。
// 连续整数固定和问题 2023年12月20日 16点45分-17点01分
# include <stdio.h>
# include <math.h>
int main()
{
int n;
printf("please input n:");
scanf("%d", & n); // input
for (int a = 1; a < n; ++a) {
double m1 = (1-2*a+sqrt((2*a-1)*(2*a-1)-4*(-2*n))) / 2.0;
// double m2 = (1-2*a-sqrt((2*a-1)*(2*a-1)-4*(-2*n))) / 2.0;
if (m1 == (int)m1) {
// printf("m1 = %f, m2 = %f\n", m1, m2);
printf("%d=%d", n, a); // output
for (int i = 1; i < m1; ++i) {
printf("+%d", a+i);
}
printf("\n");
}
}
return 0;
}
// 书上代码
# include <stdio.h>
void cntnsIntSum(int n)
{
int i, sum = 0, j;
for (int i = 1; i < n; ++i) { // 控制起点的选择,从1到n-1
j = i - 1;
while (sum < n) { // 从起点向后顺序累加
++j;
sum += j;
}
if (sum == n) {
printf("%d+...+%d = %d\n", i, j, n);
}
sum = 0;
}
}
int main()
{
int n;
printf("Please input a integer\n");
scanf("%d", & n);
cntnsIntSum(n);
return 0;
}
【6.2】表示成两个数的平方和:找出所有满足X的平方加Y的平方等于N的正整数对X和Y。
题目分析: 穷举法。双层循环就可。
// 表示成两个数的平方和 2023年12月20日17点10分-17点19分
# include <stdio.h>
# include <math.h>
int main()
{
int n;
printf("Please input n:"); // input
scanf("%d", & n);
for (int x = 1; x <= sqrt(n); ++x) {
for (int y = x; y <= sqrt(n - x*x); ++y) {
if (x*x + y*y == n) {
printf("%d = %d^2 + %d^2\n", n, x, y); // output
}
}
}
return 0;
}
总结: 书上的代码是将双重for循环放到一个函数里,然后调用这个函数。
【6.3】具有特殊性质的数:有这样一个4位数abcd等于 (ab+cd)的平方,其中ab≠cd,求这个4位数。
题目分析:穷举法。四层循环即可。
// 具有特殊性质的数 2023年12月20日17点22分-17点26分
# include <stdio.h>
void GetABCD(void) {
for (int a = 1; a < 10; ++a) { // ab是2位数,十位不为0
for (int b = 0; b < 10; ++b) {
for (int c = 1; c < 10; ++c) { // cd是2位数,十位不为0,这里书上不一样,不过我觉得我是正确的,哈哈哈~
for (int d = 0; d < 10; ++d) {
if (a*1000+b*100+c*10+d == (a*10+b+c*10+d)*(a*10+b+c*10+d)) {
printf("abcd = %d%d%d%d\n", a, b, c, d);
}
}
}
}
}
}
int main()
{
GetABCD();
return 0;
}
【6.4】验证角谷猜想:编写程序加以验证。
题目分析:按部就班。循环即可。
// 验证角谷猜想 2023年12月20日17点29分-17点34分
# include <stdio.h>
void conjecture(int num)
{
printf("%d", num);
while (num != 1) {
if (num % 2) // 奇数
num = 3 * num + 1;
else // 偶数
num /= 2;
printf("->%d", num);
}
}
int main()
{
int n;
printf("Please input n:");
scanf("%d", & n);
conjecture(n);
return 0;
}
【6.5】验证四方定理:所有自然数最多只要4个数的平方和就可以表示,编写程序加以验证。
题目分析:怎么表示最多只要4个数,这4个数是什么。如果一个自然数a本身是平方数,那么直接开方就得到了这个数m。如果一个自然数a本身不是平方数,那么开方之后取整得到m,将自然数a减去m*m再进行判断是否要循环。
// 验证四方定理 2023年12月21日09点11分-09点23分
// 这种方法不可行,n=156时输出5
# include <stdio.h>
# include <math.h>
void The_Quartet_Theroem(int num)
{
int cnt = 0;
while (1) {
double r = sqrt(num);
printf("r = %d, ", (int)r);
++cnt; // 计数
num -= ((int)r * (int)r);
if (0 == num) {
printf("cnt = %d\n", cnt);
break;
}
}
}
int main()
{
int n;
printf("Please input n:"); // input
scanf("%d", & n);
The_Quartet_Theroem(n);
return 0;
}
// 书上代码分情况讨论,至多有4个整数,分为4种情况
// 验证四方定理 2023年12月21日09点27分-09点39分
# include <stdio.h>
# include <math.h>
int mode_1(int num)
{
if ((int)sqrt(num) * (int)sqrt(num) == num) { // 这个数本身就是平方数
printf("%d*%d=%d\n", (int)sqrt(num), (int)sqrt(num), num);
return 1;
} else {
return 0;
}
}
int mode_2(int num)
{
for (int x = 1; x < sqrt(num); ++x) { // 这个数是两个平方数之和
for (int y = x; y < sqrt(num); ++y) { // 这两个数可以相等,比如8=2^2+2^2
if (x*x + y*y == num) {
printf("%d^2+%d^2=%d\n", x, y, num);
return 1;
}
}
}
return 0;
}
int mode_3(int num)
{
for (int x = 1; x < sqrt(num); ++x) { // 这个数是三个平方数之和
for (int y = x; y < sqrt(num); ++y) { // 这三个数可以相等,比如12=2^2+2^2+2^2
for (int z = y; z < sqrt(num); ++z) {
if (x*x + y*y + z*z == num) {
printf("%d^2+%d^2+%d^2=%d\n", x, y, z, num);
return 1;
}
}
}
}
return 0;
}
int mode_4(int num)
{
for (int x = 1; x < sqrt(num); ++x) { // 这个数是四个平方数之和
for (int y = x; y < sqrt(num); ++y) {
for (int z = y; z < sqrt(num); ++z) {
for (int t = z; t < sqrt(num); ++t) {
if (x*x + y*y + z*z + t*t == num) {
printf("%d^2+%d^2+%d^2+%d^2=%d\n", x, y, z, t, num);
return 1;
}
}
}
}
}
return 0;
}
void proveFourSquares(int num)
{
if (mode_1(num))
printf("It has verfied Four Squares");
else if (mode_2(num))
printf("It has verfied Four Squares");
else if (mode_3(num))
printf("It has verfied Four Squares");
else if (mode_4(num))
printf("It has verfied Four Squares");
}
int main()
{
int n;
printf("Please input a natural number\n");
scanf("%d", & n);
printf("------Step of Verification------\n");
proveFourSquares(n);
return 0;
}
【6.6】递归法寻找最小值:编写程序要求从一个整数序列中找出最小的元素,并用递归的方法实现。
题目分析:顺序查找肯定是最容易理解的,但是如何使用递归呢?这个整数序列无序,哪个地方使用递归呢?
// 递归法求最小值 2023年12月21日09点50分-10点02分
# include <stdio.h>
int getMin(int array[], int n)
{
int val1, val2, val3;
if (n == 1) { // 只有一个元素
return array[0];
} else if (n % 2 == 0) { // 序列长度为2的倍数
val1 = getMin(array, n/2); // 得到前半个序列中的最小元素val1
val2 = getMin(array+n/2, n/2); // 得到后半个序列中的最小元素val2
if (val1 < val2) // val1 < val2,返回val1
return val1;
else return val2; // val1 >= val2,返回val2
} else { // 序列长度为奇数
val1 = getMin(array, n/2); // 得到中位元素之前的子序列中的最小值
val2 = getMin(array+n/2+1, n/2); // 得到中位元素之后的子序列中的最小值
val3 = array[n/2];
if (val1 < val2) {
if (val1 < val3)
return val1;
else
return val3;
} else {
if (val2 < val3)
return val2;
else
return val3;
}
}
}
int main()
{
int n;
printf("Please input a natural number:");
scanf("%d", & n);
int arr[n];
printf("Please input the elements of this array:");
for (int i = 0; i < n; ++i) {
scanf("%d", & arr[i]);
}
int val = getMin(arr, n);
printf("The minimum element of this array is %d\n", val);
return 0;
}
总结: 书上分析是把这个整数序列分为两部分,从左序列找最小,再从右序列中找最小,重复寻找。
【6.7】寻找同构数:编写程序找出1000以内的同构数。
题目分析:穷举法。循环即可。
// 寻找同构数 2023年12月21日10点22分-10点26分
# include <stdio.h>
void findNum(void)
{
for (int i = 1; i < 1000; ++i) {
int dig = 0, k = 10;
if (i < 10)
dig = 1;
else if (i < 100) {
dig = 2;
k = 100;
} else {
dig = 3;
k = 1000;
}
//for (k = 10; k < 1000; k *= 10) // 书上代码更简洁
// if (i / k == 0)
// break;
if (i*i%k == i) {
printf("%d ", i);
}
}
}
int main()
{
printf("The Isomorphic numbers bellow 1000 are\n");
findNum();
return 0;
}
【6.8】验证尼科彻斯定理:编写程序验证任何一个整数的立方都可以表示成一串连续奇数的和。
题目分析:穷举法。循环即可。
// 验证尼科彻斯定理 2023年12月21日10点37分-10点43分
# include <stdio.h>
void Nicoqish(int num)
{
for (int i = 1; i < num*num*num; ++i) { // i为起点
int sum = 0;
for (int j = i; j < num*num*num; j += 2) { // j控制从i向后顺次累加
sum += j;
if (sum == num*num*num) { // 如果奇数序列的和等于num*num*num
printf("%d = %d", num*num*num, i); // 输出结果,程序返回
for (int k = i+2; k <= j; k += 2) {
printf("+%d", k);
}
return ;
} else if (sum > num*num*num) { // 如果奇数序列的和大于num*num*num,跳出本次循环
break;
}
}
}
printf("Error\n");
}
int main()
{
int n;
printf("Please input a integer to verify Nicoqish Law\n");
scanf("%d", & n);
Nicoqish(n);
return 0;
}
【6.9】三重回文数字:编写程序找出11~999之间的所有的三重回文数字。
题目分析:穷举法。循环即可。
// 三重回文数字 2023年12月21日10点46分-10点50分
# include <stdio.h>
long reverse(long num) // 求逆序数
{
long m = 0;
while (num) {
m = m * 10 + num % 10;
num /= 10;
}
return m;
}
int ispalindrome(long num) // 判断是否是回文数字
{
if (reverse(num) == num)
return 1;
else
return 0;
}
void func()
{
for (long i = 11; i < 1000; ++i) {
if (ispalindrome(i) && ispalindrome(i*i) && ispalindrome(i*i*i)) {
printf("%ld ", i);
}
}
}
int main()
{
func();
return 0;
}
【6.10】马克思手稿中的数学题:30个人包括男女小孩,分别花3先令、2先令、1先令,吃饭花了50先令。
题目分析:穷举法。循环即可。
// 马克思手稿中的数学题 2023年12月21日10点55分-10点58分
# include <stdio.h>
void Marx(void)
{
for (int men = 1; men <= 50 / 3; ++men) {
for (int women = 1; women <= 50 / 2; ++women) {
for (int children = 1; children <= 50; ++children) {
if (men+women+children == 30 && 3*men+2*women+children == 50) { // 如果符合条件
printf("men = %d, women = %d, children = %d\n", men, women, children); // 输出结果
}
}
}
}
}
int main()
{
printf("The solutions of Marx's topic\n");
Marx();
return 0;
}
【6.11】渔夫捕鱼问题:编个程序算出5个渔夫至少合伙捕了多少条鱼。
题目分析:穷举法。循环即可。
// 渔夫捕鱼问题 2023年12月21日11点03分-11点15分
# include <stdio.h>
int getfish(int init, int n)
{
int s = init;
while (n) {
s = 5 * s + 1;
--n;
}
return s;
}
int main()
{
printf("Fish which were gotten by fishers at least are %d", getfish(6, 4));
return 0;
}
【6.12】寻找假币:国王赏赐给大臣30枚金币,其中有一枚假币,用最少次数找到这枚假币。
题目分析:两两比较肯定效率很低。分为两部分,分别比较。类似于折半查找。
// 寻找假币 2023年12月21日11点28分-11点40分
# include <stdio.h>
int getFalseCoin(int coin[], int low, int high)
{
int sum1 = 0, sum2 = 0, sum3 = 0;
if (low + 1 == high) {
if (coin[low] < coin[high]) // 返回假币的编号
return low + 1;
else
return high + 1;
}
if ((high-low+1) % 2 == 0) { // 偶数个硬币
for (int i = low; i <= low+(high-low)/2; ++i) {
sum1 += coin[i]; // 前半段和
}
for (int i = low+(high-low)/2+1; i <= high; ++i) {
sum2 += coin[i]; // 后半段和
}
if (sum1 < sum2)
return getFalseCoin(coin, low, low+(high-low)/2);
else if (sum1 > sum2)
return getFalseCoin(coin, low+(high-low)/2+1, high);
}
if ((high-low+1) % 2 != 0) { // 奇数个硬币
for (int i = low; i <= low+(high-low)/2; ++i) {
sum1 += coin[i]; // 前半段和
}
for (int i = low+(high-low)/2; i <= high; ++i) {
sum2 += coin[i]; // 后半段和
}
sum3 = coin[low+(high-low)/2];
if (sum1 < sum2)
return getFalseCoin(coin, low, low+(high-low)/2-1);
if (sum1 > sum2)
return getFalseCoin(coin, low+(high-low)/2+1, high);
if (sum1 + sum3 == sum2 + sum3)
return low + (high-low)/2 + 1;
}
}
int main()
{
int coin[30] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2};
printf("The %dth coin is false\n", getFalseCoin(coin, 0, 29));
return 0;
}
【6.13】计算组合数:编写程序计算组合数。
题目分析:阶乘计算。算就行了。
// 计算组合数 2023年12月21日11点41分-11点45分
# include <stdio.h>
long long int fact(int num)
{
long long p = 1;
for (int i = 1; i <= num; ++i)
p *= i;
return p;
}
long long int func(int m, int n)
{
return fact(m) / (fact(n) * fact(m - n));
}
int main()
{
int m, n;
printf("Please input two integers:");
scanf("%d%d", & m, & n);
printf("The result is %lld", func(m, n));
return 0;
}
// 计算组合数 2023年12月21日11点46分-11点48分
// 书上代码,使用递归
# include <stdio.h>
int cnr(int m, int n)
{
if (m == n || n == 0)
return 1;
else
return cnr(m-1, n) + cnr(m-1, n-1);
}
int main()
{
int m, n;
printf("Please input m and n for C(m, n)\n");
scanf("%d%d", & m, & n);
printf("C(%d, %d) = %d", m, n, cnr(m, n));
return 0;
}
【6.14】递归法求幂:编写一个递归算法,计算m的n次方。
题目分析:n=0时,结果为1;n>0时,结果为m*(m的n-1次方)。算就行了。
// 递归法求幂 2023年12月21日14点38分-14点41分
# include <stdio.h>
int func(int p, int q)
{
if (q == 0)
return 1;
else
return p * func(p, q - 1);
}
int main()
{
int m, n;
printf("Please input two integers:");
scanf("%d%d", & m, & n);
printf("The result is %d", func(m, n));
return 0;
}
// 递归法求幂 2023年12月21日14点47分-14点53分
# include <stdio.h> // 书上代码
unsigned long int myPow(int m, int n)
{
if (n == 0)
return 1;
if (n == 1)
return m;
if (n % 2 == 0) {
unsigned long int tmp = myPow(m, n / 2);
return tmp * tmp;
} else {
return m * myPow(m, n - 1);
}
}
int main()
{
int m, n;
printf("Please input the bottom number:"); // 输入底数m
scanf("%d", & m);
printf("Please input the exponent number:"); // 输入指数n
scanf("%d", & n);
printf("The result of power(%d, %d) is %lu", m, n, myPow(m, n));
return 0;
}
总结: 递归法求幂比循环连乘效率要高。采用临时变量保存返回值,体现了算法的优势,提高算法的效率。注意数据类型。
【6.15】汉诺Hanoi塔:编写程序实现移动的步骤。
题目分析:经典问题,递归如何实现呢?n个盘子可以看成(n-1)个盘子和1个盘子组成的。递归结束条件是什么,递归部分怎么写?还是想不明白。
// 汉诺塔 2023年12月21日15点01分-15点20分
# include <stdio.h> // 书上代码
void move(int n, char x, char y, char z)
{
if (n == 1) // 递归结束条件,只有一个盘子,无需借助y,直接显示移动过程x到z
printf("%c-->%c\n", x, z);
else {
move(n - 1, x, z, y); // 先将n-1个盘子从x借助z移到y
printf("%c-->%c\n", x, z); // 然后将第n个盘子直接移到z,也就是显示移动过程x到z
move(n - 1, y, x, z); // 最后将y上的n-1个盘子通过x移到z
}
}
int main()
{
int n;
printf("Input disks number:");
scanf("%d", & n);
printf("The step to move %d disks:\n", n);
move(n, 'A', 'B', 'C');
return 0;
}
【6.16】选美比赛:在现场按照选手的出场顺序宣布最后得分和最后名次。
题目分析:排序问题。如何排序。
// 选美比赛 2023年12月21日15点32分-15点44分
# include <stdio.h>
struct player{
int num;
int score;
int rand;
};
void sortScore(struct player psn[], int n) // 冒泡排序
{
for (int i = 0; i < n-1; ++i) {
for (int j = 0; j < n-1-i; ++j) {
if (psn[j].score > psn[j+1].score) {
struct player tmp = psn[j];
psn[j] = psn[j+1];
psn[j+1] = tmp;
}
}
}
}
void setRand(struct player psn[], int n)
{
int k = 1;
psn[0].rand = k;
for (int i = 1; i < n; ++i) {
if (psn[i].score != psn[i-1].score) {
psn[i].rand = ++k;
} else {
psn[i].rand = k;
}
}
}
void sortNum(struct player psn[], int n)
{
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n-1-i; ++j) {
if (psn[j].num > psn[j+1].num) {
struct player tmp = psn[j];
psn[j] = psn[j+1];
psn[j+1] = tmp;
}
}
}
}
void sortRand(struct player psn[], int n)
{
sortScore(psn, n); // 以分数为关键字排序
setRand(psn, n); // 按照分数排名次
sortNum(psn, n); // 按照序号重新排序
}
int main()
{
struct player psn[7] = {{1,5,0}, {2,3,0}, {3,4,0}, {4,7,0}, {5,3,0}, {6,5,0}, {7,6,0}};
sortRand(psn, 7);
printf("num score rand\n");
for (int i = 0; i < 7; ++i)
printf("%d%6d%6d\n", psn[i].num, psn[i].score, psn[i].rand);
return 0;
}
总结: 这一章中的题目做起来不太难,容易理解并且实现。用到了穷举法和递归法解决问题,要继续加油哦!还是要多加练习哦!