《计算机常用算法及程序设计案例教程》习题解答.docx
《《计算机常用算法及程序设计案例教程》习题解答.docx》由会员分享,可在线阅读,更多相关《《计算机常用算法及程序设计案例教程》习题解答.docx(115页珍藏版)》请在冰豆网上搜索。
《计算机常用算法及程序设计案例教程》习题解答
《计算机常用算法与程序设计案例教程》
习题解答提要
习题1
1-1分数分解算法描述
把真分数a/b分解为若干个分母为整数分子为“1”的埃及分数之和:
(1)寻找并输出小于a/b的最大埃及分数1/c;
(2)若c>900000000,则退出;
(3)若c≤900000000,把差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/a)+1;
if(c>900000000)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<=n;k++)
for(j=k;j>=1;j--)
m=m+j;
因s=1+2+…+n=n(n+1)/2
时间复杂度为O(n2)。
(2)m=0;
for(j=1;j<=k/2;j++)
设n=2u+1,语句m=m+1的执行频数为
s=1+1+2+2+3+3+…+u+u=u(u+1)=(n−1)(n+1)/4
设n=2u,语句m=m+1的执行频数为
s=1+1+2+2+3+3+…+u=u2=n2/4
(3)t=1;m=0;
{t=t*k;
for(j=1;j<=k*t;j++)
因s=1+2×2!
+3×3!
+…+n×n!
=(n+1)!
−1
时间复杂度为O((n+1)!
).
(4)for(a=1;a<=n;a++)
{s=0;
for(b=a*100−1;b>=a*100−99;b−=2)
{for(x=0,k=1;k<=sqrt(b);k+=2)
if(b%k==0)
{x=1;break;}
s=s+x;
if(s==50)
printf("%ld\n",a);break;}
因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
因而有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)程序实现#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i==j||i+j==n+1)a[i][j]=0;//方阵对角线元素赋值if(i+ja[i][j]=i;//方阵上部元素赋值if(i+jj)a[i][j]=j;//方阵左部元素赋值if(i+j>n+1&&i>j)a[i][j]=n+1-i;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=n+1-j;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}}1-5据例1-2的算法,写出求解n个“1”组成的整数能被2011整除的程序。修改程序,求出n至少为多大时,n个“1”组成的整数能被2013整除?解:程序为#includevoidmain(){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",n,p);}习题22-1解不等式设n为正整数,解不等式解:上下限一般为键盘输入的a,b。//解不等式:a<1+1/(1+1/2)+...+1/(1+1/2+...+1/n)#include#includevoidmain(){longa,b,c,d,i;doublets,s;printf("请输入a,b:");scanf("%d,%d",&a,&b);i=0;ts=0;s=0;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}c=i;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}d=i-1;printf("\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.程序实现//韩信点兵#includevoidmain(){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是素数。//质因数分解乘积形式#include"math.h"#includevoidmain(){longintb,i,k,m,n,w=0;printf("[m,n]中整数分解质因数(乘积形式).\n");printf("请输入m,n:");scanf("%ld,%ld",&m,&n);for(i=m;i<=n;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);}k++;}if(b>1&&bprintf("%ld\n",b);//输出大于i平方根的因数if(b==i){printf("(素数!)\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<=n<=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。//基于素数的整数和#include#includevoidmain(){intt,j,n,k,k1,k2,a[3000];longs,smax,smin;printf("请输入整数n:");scanf("%d",&n);for(k=1;k<=n+1;k++)a[k]=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)a[k]=1;//标记第k个奇数2k-1为素数}s=3;smax=0;smin=s;for(k=2;k<=n;k++){if(a[k]+a[k+1]>=1)s+=(2*k-1)*(2*k+1);//实施代数和elses-=(2*k-1)*(2*k+1);if(s>smax){smax=s;k1=k;}//比较求最大值smaxif(s}printf("s(%d)=%ld\n",n,s);printf("当k=%d时s有最大值:%ld\n",k1,smax);printf("当k=%d时s有最小值:%ld\n",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位平方数#include#includevoidmain(){intk,m,n,t,f[10];longa,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;k<=9;k++)f[k]=0;while(w>0){m=w%10;f[m]++;w=w/10;}for(t=0,k=1;k<=9;k++)if(f[k]>1)t=1;//测试三个平方数是否有重复数字if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4{n++;printf("%2d:",n);printf("%ld=%ld^2\n",d,a);}}printf("共可组成%d个没有重复数字的7位平方数.\n",n);}2-6写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i+j<=n+1&&i<=j)a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值if(i+jj)a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值if(i+j>=n+1&&i>=j)a[i][j]=i-n/2;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
因而有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
voidmain()
{inti,j,n,a[30][30];
printf("请确定方阵阶数n:
");
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{if(i==j||i+j==n+1)
a[i][j]=0;//方阵对角线元素赋值
if(i+ja[i][j]=i;//方阵上部元素赋值if(i+jj)a[i][j]=j;//方阵左部元素赋值if(i+j>n+1&&i>j)a[i][j]=n+1-i;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=n+1-j;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}}1-5据例1-2的算法,写出求解n个“1”组成的整数能被2011整除的程序。修改程序,求出n至少为多大时,n个“1”组成的整数能被2013整除?解:程序为#includevoidmain(){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",n,p);}习题22-1解不等式设n为正整数,解不等式解:上下限一般为键盘输入的a,b。//解不等式:a<1+1/(1+1/2)+...+1/(1+1/2+...+1/n)#include#includevoidmain(){longa,b,c,d,i;doublets,s;printf("请输入a,b:");scanf("%d,%d",&a,&b);i=0;ts=0;s=0;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}c=i;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}d=i-1;printf("\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.程序实现//韩信点兵#includevoidmain(){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是素数。//质因数分解乘积形式#include"math.h"#includevoidmain(){longintb,i,k,m,n,w=0;printf("[m,n]中整数分解质因数(乘积形式).\n");printf("请输入m,n:");scanf("%ld,%ld",&m,&n);for(i=m;i<=n;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);}k++;}if(b>1&&bprintf("%ld\n",b);//输出大于i平方根的因数if(b==i){printf("(素数!)\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<=n<=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。//基于素数的整数和#include#includevoidmain(){intt,j,n,k,k1,k2,a[3000];longs,smax,smin;printf("请输入整数n:");scanf("%d",&n);for(k=1;k<=n+1;k++)a[k]=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)a[k]=1;//标记第k个奇数2k-1为素数}s=3;smax=0;smin=s;for(k=2;k<=n;k++){if(a[k]+a[k+1]>=1)s+=(2*k-1)*(2*k+1);//实施代数和elses-=(2*k-1)*(2*k+1);if(s>smax){smax=s;k1=k;}//比较求最大值smaxif(s}printf("s(%d)=%ld\n",n,s);printf("当k=%d时s有最大值:%ld\n",k1,smax);printf("当k=%d时s有最小值:%ld\n",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位平方数#include#includevoidmain(){intk,m,n,t,f[10];longa,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;k<=9;k++)f[k]=0;while(w>0){m=w%10;f[m]++;w=w/10;}for(t=0,k=1;k<=9;k++)if(f[k]>1)t=1;//测试三个平方数是否有重复数字if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4{n++;printf("%2d:",n);printf("%ld=%ld^2\n",d,a);}}printf("共可组成%d个没有重复数字的7位平方数.\n",n);}2-6写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i+j<=n+1&&i<=j)a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值if(i+jj)a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值if(i+j>=n+1&&i>=j)a[i][j]=i-n/2;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
a[i][j]=i;//方阵上部元素赋值
if(i+jj)
a[i][j]=j;//方阵左部元素赋值
if(i+j>n+1&&i>j)
a[i][j]=n+1-i;//方阵下部元素赋值
if(i+j>n+1&&ia[i][j]=n+1-j;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}}1-5据例1-2的算法,写出求解n个“1”组成的整数能被2011整除的程序。修改程序,求出n至少为多大时,n个“1”组成的整数能被2013整除?解:程序为#includevoidmain(){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",n,p);}习题22-1解不等式设n为正整数,解不等式解:上下限一般为键盘输入的a,b。//解不等式:a<1+1/(1+1/2)+...+1/(1+1/2+...+1/n)#include#includevoidmain(){longa,b,c,d,i;doublets,s;printf("请输入a,b:");scanf("%d,%d",&a,&b);i=0;ts=0;s=0;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}c=i;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}d=i-1;printf("\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.程序实现//韩信点兵#includevoidmain(){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是素数。//质因数分解乘积形式#include"math.h"#includevoidmain(){longintb,i,k,m,n,w=0;printf("[m,n]中整数分解质因数(乘积形式).\n");printf("请输入m,n:");scanf("%ld,%ld",&m,&n);for(i=m;i<=n;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);}k++;}if(b>1&&bprintf("%ld\n",b);//输出大于i平方根的因数if(b==i){printf("(素数!)\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<=n<=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。//基于素数的整数和#include#includevoidmain(){intt,j,n,k,k1,k2,a[3000];longs,smax,smin;printf("请输入整数n:");scanf("%d",&n);for(k=1;k<=n+1;k++)a[k]=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)a[k]=1;//标记第k个奇数2k-1为素数}s=3;smax=0;smin=s;for(k=2;k<=n;k++){if(a[k]+a[k+1]>=1)s+=(2*k-1)*(2*k+1);//实施代数和elses-=(2*k-1)*(2*k+1);if(s>smax){smax=s;k1=k;}//比较求最大值smaxif(s}printf("s(%d)=%ld\n",n,s);printf("当k=%d时s有最大值:%ld\n",k1,smax);printf("当k=%d时s有最小值:%ld\n",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位平方数#include#includevoidmain(){intk,m,n,t,f[10];longa,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;k<=9;k++)f[k]=0;while(w>0){m=w%10;f[m]++;w=w/10;}for(t=0,k=1;k<=9;k++)if(f[k]>1)t=1;//测试三个平方数是否有重复数字if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4{n++;printf("%2d:",n);printf("%ld=%ld^2\n",d,a);}}printf("共可组成%d个没有重复数字的7位平方数.\n",n);}2-6写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i+j<=n+1&&i<=j)a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值if(i+jj)a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值if(i+j>=n+1&&i>=j)a[i][j]=i-n/2;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
a[i][j]=n+1-j;//方阵右部元素赋值
printf("%d阶对称方阵为:
\n",n);
{for(j=1;j<=n;j++)//输出对称方阵
printf("%3d",a[i][j]);
printf("\n");
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",n,p);
习题2
2-1解不等式
设n为正整数,解不等式
上下限一般为键盘输入的a,b。
//解不等式:
a<1+1/(1+1/2)+...+1/(1+1/2+...+1/n)
{longa,b,c,d,i;
doublets,s;
printf("请输入a,b:
scanf("%d,%d",&a,&b);
i=0;ts=0;s=0;
while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}c=i;while(s{i=i+1;ts=ts+(double)1/i;s=s+1/ts;}d=i-1;printf("\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.程序实现//韩信点兵#includevoidmain(){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是素数。//质因数分解乘积形式#include"math.h"#includevoidmain(){longintb,i,k,m,n,w=0;printf("[m,n]中整数分解质因数(乘积形式).\n");printf("请输入m,n:");scanf("%ld,%ld",&m,&n);for(i=m;i<=n;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);}k++;}if(b>1&&bprintf("%ld\n",b);//输出大于i平方根的因数if(b==i){printf("(素数!)\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<=n<=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。//基于素数的整数和#include#includevoidmain(){intt,j,n,k,k1,k2,a[3000];longs,smax,smin;printf("请输入整数n:");scanf("%d",&n);for(k=1;k<=n+1;k++)a[k]=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)a[k]=1;//标记第k个奇数2k-1为素数}s=3;smax=0;smin=s;for(k=2;k<=n;k++){if(a[k]+a[k+1]>=1)s+=(2*k-1)*(2*k+1);//实施代数和elses-=(2*k-1)*(2*k+1);if(s>smax){smax=s;k1=k;}//比较求最大值smaxif(s}printf("s(%d)=%ld\n",n,s);printf("当k=%d时s有最大值:%ld\n",k1,smax);printf("当k=%d时s有最小值:%ld\n",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位平方数#include#includevoidmain(){intk,m,n,t,f[10];longa,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;k<=9;k++)f[k]=0;while(w>0){m=w%10;f[m]++;w=w/10;}for(t=0,k=1;k<=9;k++)if(f[k]>1)t=1;//测试三个平方数是否有重复数字if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4{n++;printf("%2d:",n);printf("%ld=%ld^2\n",d,a);}}printf("共可组成%d个没有重复数字的7位平方数.\n",n);}2-6写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i+j<=n+1&&i<=j)a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值if(i+jj)a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值if(i+j>=n+1&&i>=j)a[i][j]=i-n/2;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
{i=i+1;
ts=ts+(double)1/i;
s=s+1/ts;
c=i;
while(s
d=i-1;
printf("\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;
{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是素数。
//质因数分解乘积形式
#include"math.h"
{longintb,i,k,m,n,w=0;
printf("[m,n]中整数分解质因数(乘积形式).\n");
printf("请输入m,n:
scanf("%ld,%ld",&m,&n);
for(i=m;i<=n;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);
k++;
if(b>1&&b
printf("%ld\n",b);//输出大于i平方根的因数
if(b==i)
{printf("(素数!
)\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<=n<=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;
printf("请输入整数n:
for(k=1;k<=n+1;k++)a[k]=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)a[k]=1;//标记第k个奇数2k-1为素数
s=3;smax=0;smin=s;
for(k=2;k<=n;k++)
{if(a[k]+a[k+1]>=1)
s+=(2*k-1)*(2*k+1);//实施代数和
s-=(2*k-1)*(2*k+1);
if(s>smax){smax=s;k1=k;}//比较求最大值smax
if(s}printf("s(%d)=%ld\n",n,s);printf("当k=%d时s有最大值:%ld\n",k1,smax);printf("当k=%d时s有最小值:%ld\n",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位平方数#include#includevoidmain(){intk,m,n,t,f[10];longa,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;k<=9;k++)f[k]=0;while(w>0){m=w%10;f[m]++;w=w/10;}for(t=0,k=1;k<=9;k++)if(f[k]>1)t=1;//测试三个平方数是否有重复数字if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4{n++;printf("%2d:",n);printf("%ld=%ld^2\n",d,a);}}printf("共可组成%d个没有重复数字的7位平方数.\n",n);}2-6写出例2-2中对称方阵的完整程序,并运行程序。对称方阵程序:#includevoidmain(){inti,j,n,a[30][30];printf("请确定方阵阶数n:");scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i+j<=n+1&&i<=j)a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值if(i+jj)a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值if(i+j>=n+1&&i>=j)a[i][j]=i-n/2;//方阵下部元素赋值if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
printf("s(%d)=%ld\n",n,s);
printf("当k=%d时s有最大值:
%ld\n",k1,smax);
printf("当k=%d时s有最小值:
%ld\n",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;a<=c;a++)
{d=a*a;w=d;//确保d为平方数
for(k=0;k<=9;k++)f[k]=0;
while(w>0)
{m=w%10;f[m]++;w=w/10;}
for(t=0,k=1;k<=9;k++)
if(f[k]>1)t=1;//测试三个平方数是否有重复数字
if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4
{n++;
printf("%2d:
",n);
printf("%ld=%ld^2\n",d,a);
printf("共可组成%d个没有重复数字的7位平方数.\n",n);
2-6写出例2-2中对称方阵的完整程序,并运行程序。
对称方阵程序:
{if(i+j<=n+1&&i<=j)
a[i][j]=(n+1)/2-i+1;//方阵上部元素赋值
a[i][j]=(n+1)/2-j+1;//方阵左部元素赋值
if(i+j>=n+1&&i>=j)
a[i][j]=i-n/2;//方阵下部元素赋值
if(i+j>n+1&&ia[i][j]=j-n/2;//方阵右部元素赋值}printf("%d阶对称方阵为:\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++)//输出对称方阵printf("%3d",a[i][j]);printf("\n");}} 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统计解的个数。(2)程序实现//四则运算式#includevoidmain(){intx,y,t,k,a,b,c,d,e,n=0;intm[6],f[11];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;d<=9;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<=9;x++)f[x]=0;for(k=1;k<=5;k++){y=m[k];while(y>0){x=y%10;f[x]=f[x]+1;y=(y-x)/10;//分离数字f数组统计}}for(t=0,x=1;x<=9;x++)if(f[x]!=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是否为素数,用变量s统计这50个奇数中的合数的个数。对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。(2)合数世纪程序设计//合数世纪探求#include#includevoidmain(){longa,b,k;ints,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;k<=sqrt(b);k+=2)if(b%k==0){x=1;break;}if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求s=s+x;//年号b为合数时,x=1,s增1}if(s==50)//s=50,即50个奇数均为合数{printf("最早出现的合数世纪为%ld世纪!\n",a);break;}}}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个合数#include#includevoidmain(){longc,d,f,m,j;intt,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){for(t=0,j=3;j<=sqrt(m);j+=2)if(m%j==0)//实施试商{t=1;break;}if(t==0&&m-f>n)//满足条件即行输出{printf("最小的%d个连续合数区间为:",n);printf("[%ld,%ld]。\n",f+1,f+n);getch();return;}if(t==0)f=m;//每求出一个素数m后赋值给f}if(m>d){c=d+2;d=c+10000;}//每一轮试商后改变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)(2)图2-8b数组分布示意图可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置:
a[i][j]=j-n/2;//方阵右部元素赋值
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;a<=98;a++)
for(b=2;b<=9;b++)
for(c=123;c<=987;c++)//对a,b,c,d实施枚举
for(d=2;d<=9;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<=9;x++)f[x]=0;
for(k=1;k<=5;k++)
{y=m[k];
while(y>0)
{x=y%10;f[x]=f[x]+1;
y=(y-x)/10;//分离数字f数组统计
for(t=0,x=1;x<=9;x++)
if(f[x]!
=1)
{t=1;break;}//检验数字0--9各只出现一次
if(t==0)//输出一个解,用n统计个数
%2d*%1d+%3d/%1d-%2d=0\n",n,a,b,c,d,e);
printf("n=%d.\n",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;
{a++;s=0;//检验a世纪
for(b=a*100-99;b<=a*100-1;b+=2)//穷举a世纪奇数年号b
{x=0;
for(k=3;k<=sqrt(b);k+=2)
if(x==0)break;//当前为非合数世纪时,跳出循环进行下世纪的探求
s=s+x;//年号b为合数时,x=1,s增1
if(s==50)//s=50,即50个奇数均为合数
{printf("最早出现的合数世纪为%ld世纪!
\n",a);
2-9最小连续n个合数
试求出最小的连续n个合数。
(其中n是键盘输入的任意正整数。
求出区间[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,继续试商下去,直到找出所要求的解。
//求最小的连续n个合数
{longc,d,f,m,j;
intt,n;
printf("求最小的n个连续合数.\n");
printf("请输入n:
c=3;d=c+10000;
f=3;
{for(m=c;m<=d;m+=2)
{for(t=0,j=3;j<=sqrt(m);j+=2)
if(m%j==0)//实施试商
if(t==0&&m-f>n)//满足条件即行输出
{printf("最小的%d个连续合数区间为:
printf("[%ld,%ld]。
\n",f+1,f+n);
getch();return;
if(t==0)f=m;//每求出一个素数m后赋值给f
if(m>d)
{c=d+2;d=c+10000;}//每一轮试商后改变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
(2)
图2-8b数组分布示意图
可以根据约定对b
(1)、b(7)和b(4)的值进行循环探索,设置:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1