《计算机常用算法及程序设计案例教程》习题解答Word文档格式.docx
- 文档编号:19132289
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:96
- 大小:152.48KB
《计算机常用算法及程序设计案例教程》习题解答Word文档格式.docx
《《计算机常用算法及程序设计案例教程》习题解答Word文档格式.docx》由会员分享,可在线阅读,更多相关《《计算机常用算法及程序设计案例教程》习题解答Word文档格式.docx(96页珍藏版)》请在冰豆网上搜索。
(3)t=1;
m=0;
{t=t*k;
for(j=1;
=k*t;
}
因s=1+2×
2!
+3×
3!
+…+n×
n!
=(n+1)!
−1
时间复杂度为O((n+1)!
).
(4)for(a=1;
a<
a++)
{s=0;
for(b=a*100−1;
b>
=a*100−99;
b−=2)
{for(x=0,k=1;
=sqrt(b);
k+=2)
if(b%k==0)
{x=1;
break;
s=s+x;
if(s==50)
printf("
%ld\n"
a);
因a循环n次;
对每一个a,b循环50次;
对每一个b,k循环
次。
因而k循环体的执行次数s满足
时间复杂度为O(
)。
1-3若p(n)是n的多项式,证明:
O(log(p(n)))=O(logn)。
证:
设m为正整数,p(n)=a1×
nm+a2×
nm-1+…+am×
n,
取常数c>
ma1+(m-1)a2+…+am,则
log(p(n))=ma1×
logn+(m-1)a2×
logn+…=(ma1+(m-1)a2+…)×
logn
<
clogn
因而有O(log(p(n)))=O(logn)。
1-4构建对称方阵
观察图1-5所示的7阶对称方阵:
图1-57阶对称方阵
试构造并输出以上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<
stdio.h>
voidmain()
{inti,j,n,a[30][30];
请确定方阵阶数n:
"
);
scanf("
%d"
&
n);
for(i=1;
i<
i++)
{if(i==j||i+j==n+1)
a[i][j]=0;
//方阵对角线元素赋值
if(i+j<
n+1&
&
i<
j)
a[i][j]=i;
//方阵上部元素赋值
i>
a[i][j]=j;
//方阵左部元素赋值
if(i+j>
a[i][j]=n+1-i;
//方阵下部元素赋值
a[i][j]=n+1-j;
//方阵右部元素赋值
%d阶对称方阵为:
\n"
n);
i++)
{for(j=1;
j++)//输出对称方阵
%3d"
a[i][j]);
1-5据例1-2的算法,写出求解n个“1”组成的整数能被2011整除的程序。
修改程序,求出n至少为多大时,n个“1”组成的整数能被2013整除?
程序为
{inta,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,p);
习题2
2-1解不等式
设n为正整数,解不等式
上下限一般为键盘输入的a,b。
//解不等式:
a<
1+1/(1+1/2)+...+1/(1+1/2+...+1/n)<
b
#include<
math.h>
{longa,b,c,d,i;
doublets,s;
请输入a,b:
%d,%d"
a,&
b);
i=0;
ts=0;
s=0;
while(s<
a)
{i=i+1;
ts=ts+(double)1/i;
s=s+1/ts;
c=i;
b)
{i=i+1;
s=s+1/ts;
d=i-1;
\n满足不等式的正整数n为:
%ld≤n≤%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(mod5)
x=6z+5x=5(mod6)
x=7u+4x=4(mod7)
x=11v+10x=10(mod11)
其中y,z,u,v都为正整数。
试求满足以上方程组的最小正整数x。
应用枚举可得到至少的兵数。
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.程序实现
//韩信点兵
{longintx;
x=65;
while
(1)
{x=x+66;
if(x%5==1&
x%7==4)
{printf("
至少有兵:
%ld个。
"
x);
break;
}
2-3分解质因数
对给定区间[m,n]的正整数分解质因数,每一整数表示为质因数从小到大顺序的乘积形式。
如果被分解的数本身是素数,则注明为素数。
例如,2012=2*2*503,2011=(素数!
对区间中的每一个整数i(b=i),用k(2——sqrt(i))试商:
若不能整除,说明该数k不是b的因数,k增1后继续试商。
若能整除,说明该数k是b的因数,打印输出"
k*"
;
b除以k的商赋给b(b=b/k)后继续用k试商(注意,可能有多个k因数),直至不能整除,k增1后继续试商。
按上述从小至大试商确定的因数显然为质因数。
如果有大于sqrt(n)的因数(至多一个!
),在试商循环结束后要注意补上,不要遗失。
如果整个试商后b的值没有任何缩减,仍为原待分解数n,说明n是素数,作素数说明标记。
若k是b的因数,按格式输出,然后b=b/k后继续试商k。
若k不是b的因数,则k增1后继续。
若上述试商完成后1<
b<
i,说明i有一个大于sqrt(i)的因数,要补上该因数。
若试商后b还是原来的i,则i是素数。
//质因数分解乘积形式
#include"
math.h"
{longintb,i,k,m,n,w=0;
[m,n]中整数分解质因数(乘积形式).\n"
请输入m,n:
scanf("
%ld,%ld"
m,&
for(i=m;
i++)//i为待分解的整数
{printf("
%ld="
i);
b=i;
k=2;
while(k<
=sqrt(i))//k为试商因数
{if(b%k==0)
{b=b/k;
if(b>
1)
{printf("
%ld*"
k);
continue;
//k为质因数,返回再试
if(b==1)printf("
%ld\n"
k++;
if(b>
1&
b<
i)
b);
//输出大于i平方根的因数
if(b==i)
(素数!
)\n"
w++;
}//b=i,表示i无质因数
2-4基于素数代数和的最大最小
定义和:
(和式中第k项±
(2k-1)*(2k+1)的符号识别:
当(2k-1)与(2k+1)中至少有一个素数,取“+”;
其余取“-”。
例如和式中第13项取“-”,即为-25*27。
)
1)求s(2011)。
2)设1<
=n<
=2011,当n为多大时,s(n)最大。
3)设1<
=2011,当n为多大时,s(n)最小。
代数和式中各项的符号并不是简单的正负相间,而是随着构成素数而改变。
因而在求和之前应用“试商判别法”对第k个奇数2k-1是否为素数进行标注:
若2k-1为素数,标注a[k]=1;
否则,若2k-1不是素数,a[k]=0。
设置k循环(1——n),循环中分别情况求和:
若a[k]+a[k+1]>
=1,即(2k-1)与(2k+1)中至少有一个素数,实施“+”;
否则,若a[k]+a[k+1]==0,即(2k-1)与(2k+1)中没有素数,实施“-”。
同时,设置最大值变量smax,最小值变量smin。
在循环中,每计算一个和值s,与smax比较确定最大值,同时记录此时的项数k1;
与smin比较确定最小值,同时记录此时的项数k2。
//基于素数的整数和
{intt,j,n,k,k1,k2,a[3000];
longs,smax,smin;
请输入整数n:
=n+1;
k++)a[k]=0;
for(k=2;
{for(t=0,j=3;
=sqrt(2*k-1);
j+=2)
if((2*k-1)%j==0)
{t=1;
if(t==0)a[k]=1;
//标记第k个奇数2k-1为素数
s=3;
smax=0;
smin=s;
{if(a[k]+a[k+1]>
=1)
s+=(2*k-1)*(2*k+1);
//实施代数和
else
s-=(2*k-1)*(2*k+1);
if(s>
smax){smax=s;
k1=k;
}//比较求最大值smax
if(s<
smin){smin=s;
k2=k;
}//比较求最大值smin
s(%d)=%ld\n"
n,s);
当k=%d时s有最大值:
%ld\n"
k1,smax);
当k=%d时s有最小值:
k2,smin);
2-5特定数字组成的平方数
用数字2,3,5,6,7,8,9可组成多少个没有重复数字的7位平方数?
求出最小7位数的平方根b,最大7位数的平方根c.
用a枚举[b,c]中的所有整数,计算d=a*a,这样确保所求平方数在d中。
设置f数组统计d中各个数字的个数。
如果f[3]=2,即平方数d中有2个“3”。
检测若f[k]>
1(k=0——9),说明d中存在有重复数字,返回。
在不存在重复数字的情形下,检测若f[0]+f[1]+f[4]=0,说明7位平方数d中没有数字“0”,“1”,“4”,d满足题意要求,打印输出。
//组成没有重复数字的7位平方数
{intk,m,n,t,f[10];
longa,b,c,d,w;
n=0;
b=sqrt(2356789);
c=sqrt(9876532);
for(a=b;
=c;
{d=a*a;
w=d;
//确保d为平方数
for(k=0;
=9;
k++)f[k]=0;
while(w>
0)
{m=w%10;
f[m]++;
w=w/10;
for(t=0,k=1;
if(f[k]>
1)t=1;
//测试三个平方数是否有重复数字
if(t==0&
f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4
{n++;
%2d:
%ld=%ld^2\n"
d,a);
共可组成%d个没有重复数字的7位平方数.\n"
2-6写出例2-2中对称方阵的完整程序,并运行程序。
对称方阵程序:
{if(i+j<
=n+1&
=j)
a[i][j]=(n+1)/2-i+1;
if(i+j<
a[i][j]=(n+1)/2-j+1;
if(i+j>
a[i][j]=i-n/2;
//方阵下部元素赋值
a[i][j]=j-n/2;
//方阵右部元素赋值
j++)//输出对称方阵
2-7四则运算式
把数字1,2,...,9这9个数字填入以下含加减乘除的综合运算式中的9个□中,使得该式成立
□□×
□+□□□÷
□-□□=0
要求数字1,2,...,9这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(1—9)的个数。
若某一f(x)不为1,不满足数字1,2,...,9这九个数字都出现一次且只出现一次,标记t=1.
若所有f(x)全为1,满足数字1,2,...,9这九个数字都出现一次且只出现一次,保持标记t=0,则输出所得的完美综合运算式。
设置n统计解的个数。
//四则运算式
{intx,y,t,k,a,b,c,d,e,n=0;
intm[6],f[11];
for(a=12;
=98;
for(b=2;
b++)
for(c=123;
c<
=987;
c++)//对a,b,c,d实施枚举
for(d=2;
d<
d++)
{x=c/d;
e=a*b+x;
if(c!
=x*d||e>
100)continue;
m[1]=a;
m[2]=c;
m[3]=e;
m[4]=b;
m[5]=d;
for(x=0;
x<
x++)f[x]=0;
=5;
{y=m[k];
while(y>
{x=y%10;
f[x]=f[x]+1;
y=(y-x)/10;
//分离数字f数组统计
for(t=0,x=1;
x++)
if(f[x]!
=1)
break;
}//检验数字0--9各只出现一次
if(t==0)//输出一个解,用n统计个数
%2d:
%2d*%1d+%3d/%1d-%2d=0\n"
n,a,b,c,d,e);
n=%d.\n"
2-8合数世纪探求
定义一个世纪的100个年号中不存在一个素数,即100个年号全为合数的世纪称为合数世纪。
探索最早的合数世纪。
应用穷举搜索,设置a世纪的的50个奇数年号(偶数年号无疑均为合数)为b,用k试商判别b是否为素数,用变量s统计这50个奇数中的合数的个数。
对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。
(2)合数世纪程序设计
//合数世纪探求
{longa,b,k;
ints,x;
a=1;
while
(1)
{a++;
//检验a世纪
for(b=a*100-99;
=a*100-1;
b+=2)//穷举a世纪奇数年号b
{x=0;
for(k=3;
if(b%k==0)
{x=1;
if(x==0)break;
//当前为非合数世纪时,跳出循环进行下世纪的探求
//年号b为合数时,x=1,s增1
if(s==50)//s=50,即50个奇数均为合数
最早出现的合数世纪为%ld世纪!
2-9最小连续n个合数
试求出最小的连续n个合数。
(其中n是键盘输入的任意正整数。
(1)设计要点
求出区间[c,d]的所有素数(区间起始数c可由小到大递增),检验其中每相邻两素数之差。
若某相邻的两素数m,f之差大于n,即m-f>
n,则区间[f+1,f+n]中的n个数为最小的连续n个合数。
应用试商法求指定区间[c,d](约定起始数c=3,d=c+10000)上的所有素数。
求出该区间的一个素数m,设前一个素数为f,判别:
若m-f>
n,则输出结果[f+1,f+n]后结束;
否则,作赋值f=m,为求下一个素数作准备。
如果在区间[c,d]中没有满足条件的解,则作赋值:
c=d+2,d=c+10000,继续试商下去,直到找出所要求的解。
(2)程序实现
//求最小的连续n个合数
{longc,d,f,m,j;
intt,n;
求最小的n个连续合数.\n"
请输入n:
c=3;
d=c+10000;
f=3;
{for(m=c;
m<
=d;
m+=2)
{for(t=0,j=3;
=sqrt(m);
if(m%j==0)//实施试商
}
m-f>
n)//满足条件即行输出
最小的%d个连续合数区间为:
printf("
[%ld,%ld]。
\n"
f+1,f+n);
getch();
if(t==0)f=m;
//每求出一个素数m后赋值给f
if(m>
d)
{c=d+2;
}//每一轮试商后改变c,d转下一轮
2-10和积9数字三角形
求解和为给定的正整数s(s≥45)的9个互不相等的正整数填入9数字三角形,使三角形三边上的4个数字之和相等(s1)且三边上的4个数字之积也相等(s2)。
图2-79数字三角形
(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-8b数组分布示意图
可以根据约定对b
(1)、b(7)和b(4)的值进行循环探索,设置:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机常用算法及程序设计案例教程 计算机 常用 算法 程序设计 案例 教程 习题 解答