1、计算机常用算法与程序的设计案例教程习题解答计算机常用算法与程序设计案例教程习题解答提要习题11-1 分数分解算法描述把真分数a/b分解为若干个分母为整数分子为“1”的埃及分数之和: (1) 寻找并输出小于a/b的最大埃及分数1/c; (2) 若c900000000,则退出; (3) 若c900000000,把差a/b-1/c整理为分数a/b,若a/b为埃及分数,则输出后结束。 (4) 若a/b不为埃及分数,则继续(1)、(2)、(3)。试描述以上算法。解:设 (这里int(x)表示取正数x的整数),注意到,有 算法描述:令c=d+1,则 input (a,b) while(1) c=int(b
2、/a)+1; if(c900000000) return; else print(1/c+); a=a*c-b; b=b*c; / a,b迭代,为选择下一个分母作准备 if(a=1) print(1/b);return; 1-2 求出以下程序段所代表算法的时间复杂度(1)m=0; for(k=1;k=1;j-) m=m+j; 解:因s=1+2+n=n(n+1)/2 时间复杂度为O(n2)。(2)m=0; for(k=1;k=n;k+) for(j=1;j=k/2;j+) m=m+j;解:设n=2u+1,语句m=m+1的执行频数为s=1+1+2+2+3+3+u+u=u(u+1)=(n1)(n+1
3、)/4设n=2u,语句m=m+1的执行频数为s=1+1+2+2+3+3+u=u2=n2/4时间复杂度为O(n2)。(3)t=1;m=0; for(k=1;k=n;k+) t=t*k; for(j=1;j=k*t;j+) m=m+j; 解:因s=1+22!+ 33!+ nn!=(n+1)!1时间复杂度为O(n+1)!).(4)for(a=1;a=a*10099;b=2) for(x=0,k=1;kma1+(m-1)a2+am, 则log(p(n)=ma1logn+(m-1)a2logn+=(ma1+(m-1)a2+)logn clogn因而有O(log(p(n)=O(logn)。1-4 构建对称
4、方阵观察图1-5所示的7阶对称方阵: 图1-5 7阶对称方阵试构造并输出以上n阶对称方阵。解:这是一道培养与锻炼我们的观察能力与归纳能力的案例,一个一个元素枚举赋值显然行不通,必须全局着眼,分区域归纳其构造特点,分区域枚举赋值。(1) 设计要点设方阵中元素的行号为i,列号为j。可知主对角线:i=j;次对角线:i+j=n+1。两对角线赋值“0”。按两条对角线把方阵分成上部、左部、右部与下部4个区,如图1-6所示。图1-6 对角线分成的4个区上部按行号i赋值;下部按行号函数n+1-i赋值。左部按列号j赋值;右部按列号函数n+1-j赋值。(2) 程序实现#include void main()int
5、 i,j,n,a3030; printf( 请确定方阵阶数n: ); scanf(%d,&n); for(i=1;i=n;i+) for(j=1;j=n;j+) if(i=j | i+j=n+1) aij=0; / 方阵对角线元素赋值 if(i+jn+1 & ij) aij=i; / 方阵上部元素赋值 if(i+jj) aij=j; / 方阵左部元素赋值 if(i+jn+1 & ij) aij=n+1-i; / 方阵下部元素赋值 if(i+jn+1 & ij) aij=n+1-j; / 方阵右部元素赋值 printf( %d阶对称方阵为:n,n); for(i=1;i=n;i+) for(j=
6、1;j=n;j+) / 输出对称方阵 printf(%3d,aij); printf(n); 1-5 据例1-2的算法,写出求解n个“1”组成的整数能被2011整除的程序。修改程序,求出 n至少为多大时,n个“1”组成的整数能被2013整除?解:程序为#include void main() int a,c,p,n; p=2011;c=1111;n=4; / 变量c与n赋初值 while(c!=0) / 循环模拟整数竖式除法 a=c*10+1;c=a%p;n=n+1; / 每试商一位n增1 printf( 由 %d 个1组成的整数能被 %d 整除。n,n,p);习题22-1 解不等式设n为正整
7、数,解不等式解:上下限一般为键盘输入的a,b。/ 解不等式: a1+1/(1+1/2)+.+1/(1+1/2+.+1/n)b#include #includevoid main() long a,b,c,d,i; double ts,s; printf( 请输入a,b: ); scanf(%d,%d,&a,&b); i=0;ts=0;s=0; while(sa) i=i+1; ts=ts+(double)1/i; s=s+1/ts; c=i; while(sb) i=i+1; ts=ts+(double)1/i; s=s+1/ts; d=i-1; printf(n 满足不等式的正整数n为: %
8、ldn%ld n,c,d);2-2 韩信点兵韩信在点兵的时候,为了知道有多少个兵,同时又能保住军事机密,便让士兵排队报数。按从1至5报数,记下最末一个士兵报的数为1;再按从1至6报数,记下最末一个士兵报的数为5;再按1至7报数,记下最末一个报的数为4;最后按1至11报数,最末一个士兵报的数为10。你知道韩信至少有多少兵?1. 求解要点设兵数为x,则x满足下述的同余方程组: x=5y+1 即 x=1 (mod 5) x=6z+5 x=5 (mod 6) x=7u+4 x=4 (mod 7) x=11v+10 x=10 (mod 11)其中y,z,u,v都为正整数。试求满足以上方程组的最小正整数x
9、。应用枚举可得到至少的兵数。x从1开始递增1取值枚举当然可以,但不必要。事实上枚举次数可联系问题的具体实际大大缩减。(1) 注意到x除11余10,于是可设置x从21开始,以步长11递增。此时,只要判别前三个条件即可。(2) 由以上第2,4两方程知x+1为11的倍数,也为6的倍数。而11与6互素,因而x+1必为66的倍数。于是取x=65开始,以步长66递增。此时,只要判别x%5=1与x%7=4 两个条件即可。这样可算得满足条件的最小整数x即点兵的数量。 2. 程序实现/ 韩信点兵 #include void main() long int x; x=65; while(1) x=x+66; if
10、(x%5=1 & x%7=4) printf(至少有兵: %ld 个。,x); break; 2-3 分解质因数对给定区间m,n的正整数分解质因数,每一整数表示为质因数从小到大顺序的乘积形式。如果被分解的数本身是素数,则注明为素数。例如, 2012=2*2*503, 2011=(素数!)。解:对区间中的每一个整数i(b=i),用k(2sqrt(i)试商:若不能整除,说明该数k不是b的因数,k增1后继续试商。若能整除,说明该数k是b的因数,打印输出k*;b除以k的商赋给b(b=b/k)后继续用k试商(注意,可能有多个k因数),直至不能整除,k增1后继续试商。按上述从小至大试商确定的因数显然为质因
11、数。如果有大于sqrt(n)的因数(至多一个!),在试商循环结束后要注意补上,不要遗失。如果整个试商后b的值没有任何缩减,仍为原待分解数n,说明n是素数,作素数说明标记。若k是b的因数,按格式输出,然后b=b/k后继续试商k。若k不是b的因数,则k增1后继续。若上述试商完成后1bi,说明i有一个大于sqrt(i)的因数,要补上该因数。若试商后b还是原来的i,则i是素数。/ 质因数分解乘积形式 #includemath.h#include void main()long int b,i,k,m,n,w=0;printf(m,n中整数分解质因数(乘积形式).n);printf(请输入m,n:);s
12、canf(%ld,%ld,&m,&n);for(i=m;i=n;i+) / i为待分解的整数 printf(%ld=,i); b=i;k=2; while(k1) printf(%ld*,k);continue; / k为质因数,返回再试 if(b=1) printf(%ldn,k); k+; if(b1 & bi) printf(%ldn,b); / 输出大于i平方根的因数 if(b=i) printf(素数!)n);w+; / b=i,表示i无质因数 2-4 基于素数代数和的最大最小定义和: (和式中第k项(2k-1)*(2k+1)的符号识别:当(2k-1)与(2k+1)中至少有一个素数,
13、取“+”;其余取“-”。例如和式中第13项取“-”,即为-25*27。)1) 求s(2011)。2) 设1=n=2011,当n为多大时,s(n)最大。3) 设1=n=1,即(2k-1)与(2k+1)中至少有一个素数,实施“+”;否则,若ak+ak+1=0,即(2k-1)与(2k+1)中没有素数,实施“-”。同时,设置最大值变量smax,最小值变量smin。在循环中,每计算一个和值s,与smax比较确定最大值,同时记录此时的项数k1;与smin比较确定最小值,同时记录此时的项数k2。/ 基于素数的整数和 #include#includevoid main() int t,j,n,k,k1,k2,
14、a3000; long s,smax,smin; printf( 请输入整数n: ); scanf(%d,&n); for(k=1;k=n+1;k+) ak=0; for(k=2;k=n+1;k+) for(t=0,j=3;j=sqrt(2*k-1);j+=2) if(2*k-1)%j=0) t=1;break; if(t=0) ak=1; / 标记第k个奇数2k-1为素数 s=3;smax=0;smin=s; for(k=2;k=1) s+=(2*k-1)*(2*k+1); / 实施代数和 else s-=(2*k-1)*(2*k+1); if(ssmax)smax=s;k1=k; / 比较
15、求最大值smax if(s1(k=09),说明d中存在有重复数字,返回。在不存在重复数字的情形下,检测若f0+f1+f4=0,说明7位平方数d中没有数字“0”,“1”,“4”,d满足题意要求,打印输出。/ 组成没有重复数字的7位平方数 #include #include void main()int k,m,n,t,f10; long a,b,c,d,w;n=0;b=sqrt(2356789);c=sqrt(9876532);for(a=b;a=c;a+)d=a*a; w=d; / 确保d为平方数 for(k=0;k0) m=w%10;fm+;w=w/10; for(t=0,k=1;k1) t
16、=1; / 测试三个平方数是否有重复数字 if(t=0 & f0+f1+f4=0) / 测试平方数中没有数字0,1,4 n+; printf( %2d: ,n); printf( %ld=%ld2 n,d,a); printf( 共可组成%d个没有重复数字的7位平方数.n,n); 2-6 写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#include void main()int i,j,n,a3030; printf( 请确定方阵阶数n: ); scanf(%d,&n); for(i=1;i=n;i+) for(j=1;j=n;j+) if(i+j=n+1 & i=j) aij
17、=(n+1)/2-i+1; / 方阵上部元素赋值 if(i+jj) aij=(n+1)/2-j+1; / 方阵左部元素赋值 if(i+j=n+1 & i=j) aij=i-n/2; / 方阵下部元素赋值 if(i+jn+1 & ij) aij=j-n/2; / 方阵右部元素赋值 printf( %d阶对称方阵为:n,n); for(i=1;i=n;i+) for(j=1;j=n;j+) / 输出对称方阵 printf(%3d,aij); printf(n); 2-7 四则运算式把数字1,2,.,9这9个数字填入以下含加减乘除的综合运算式中的9个中,使得该式成立+-=0 要求数字1,2,.,9这
18、9个数字在各式中都出现一次且只出现一次,且约定数字“1”不出现在数式的一位数中(即排除各式中的各个1位数为1这一平凡情形)。(1) 求解要点设式右的5个整数从左至右分别为a,b,c,d,e,其中a,e为二位整数,b,d为大于1的一位整数,c为三位整数。设置a,b,c,d循环,对每一组a,b,c,d,计算e=a*b+c/d。若其中的c/d非整数,或所得e非二位数,则返回。然后分别对5个整数进行数字分离,设置f数组对5个整数分离的共9个数字进行统计,f(x)即为数字x(19)的个数。若某一f(x)不为1,不满足数字1,2,.,9这九个数字都出现一次且只出现一次,标记t=1.若所有f(x)全为1,满
19、足数字1,2,.,9这九个数字都出现一次且只出现一次,保持标记t=0, 则输出所得的完美综合运算式。设置n统计解的个数。(2) 程序实现/ 四则运算式 #include void main()int x,y,t,k,a,b,c,d,e,n=0; int m6,f11; for(a=12;a=98;a+) for(b=2;b=9;b+) for(c=123;c=987;c+) / 对a,b,c,d 实施枚举 for(d=2;d100) continue; m1=a;m2=c;m3=e;m4=b;m5=d; for(x=0;x=9;x+) fx=0; for(k=1;k0) x=y%10;fx=f
20、x+1;y=(y-x)/10; / 分离数字f数组统计 for(t=0,x=1;x=9;x+) if(fx!=1) t=1; break; / 检验数字0-9各只出现一次 if(t=0) / 输出一个解,用n统计个数 n+; printf(%2d: %2d*%1d+%3d/%1d-%2d=0 n,n,a,b,c,d,e); printf( n=%d.n,n); 2-8 合数世纪探求定义一个世纪的100个年号中不存在一个素数,即100个年号全为合数的世纪称为合数世纪。探索最早的合数世纪。(1) 设计要点应用穷举搜索,设置a世纪的的50个奇数年号(偶数年号无疑均为合数)为b,用k试商判别b是否为素
21、数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2) 合数世纪程序设计/ 合数世纪探求 #include #include void main()long a,b,k; int s,x; a=1; while (1) a+;s=0; / 检验a世纪 for(b=a*100-99;b=a*100-1;b+=2) / 穷举a世纪奇数年号b x=0; for(k=3;kn,则区间f+1,f+n中的n个数为最小的连续n个合数。应用试商法求指定区间c,d(约定起始数c=3,d=c+10000)上的所有素数。求
22、出该区间内的一个素数m,设前一个素数为f,判别:若m-fn,则输出结果f+1,f+n后结束;否则,作赋值f=m,为求下一个素数作准备。如果在区间c,d中没有满足条件的解,则作赋值:c=d+2,d=c+10000,继续试商下去,直到找出所要求的解。 (2) 程序实现/ 求最小的连续n个合数 #include #include void main() long c,d,f,m,j; int t,n; printf( 求最小的n个连续合数.n); printf( 请输入n:); scanf(%d,&n); c=3;d=c+10000; f=3; while(1) for(m=c;m=d;m+=2)
23、for(t=0,j=3;jn) / 满足条件即行输出 printf(最小的%d个连续合数区间为:,n); printf(%ld,%ld。 n,f+1,f+n); getch();return; if(t=0) f=m; / 每求出一个素数m后赋值给f if(md) c=d+2;d=c+10000; / 每一轮试商后改变c,d转下一轮 2-10 和积9数字三角形求解和为给定的正整数s(s45)的9个互不相等的正整数填入9数字三角形,使三角形三边上的4个数字之和相等(s1)且三边上的4个数字之积也相等(s2)。 图2-7 9数字三角形(1)求解要点。把和为s的9个正整数存储于b数组b(1),b(9)中,分布如下图所示。为避免重复,不妨约定三角形中数字“下小上大、左小右大”,即b(1)b(7)b(4)且b(2)b(3)且b(6)b(5)且b(9)b(8)。图2-8 b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1