*运行结果
The new symmetrical number kelometers is:95959. The velocity of the car is:50.00 *思考题
将一个数的数码倒过来所得到的新数叫原数的反序数。如果一个数等于它的反序数,则称它为对称数。求不超过1993的最大的二进制的对称数。
23.由两个平方三位数获得三个平方二位数
已知两个平方三位数abc和xyz,其中a、b、c、x、y、z未必所指向的数组中
————————————————*/ void f(int n,float* s) { int k;
for(k=1000;k>=10;++s) {
*s = (n%k) /(k/10); k /=10; } }
*运行结果
是不同的;而ax、by、cz是三个平方二位数。请编程求三位数abc和xyz。 *问题分析与算法设计
任取两个平方三位数n和n1,将n从高向低分解为a、b、c,将n1从高到低分解为x、y、z。判断ax、by、cz是否均为完全平方数。 *程序说明与注释 #include
float a[3],b[3];
print(\are:\\n\
for(i=11;i<=31;++i) //穷举平方三位数的取值范围 for(t=11;t<=31;++t) {
f(i*i,a); //分解平方三位数的各位,每位数字分别存入数组中 f(t*t,b);
if(sqrt(a[0]*10+b[0]) == (int)sqrt(a[0]*10+b[0]) && sqrt(a[1]*10+b[1]) == (int)sqrt(a[1]*10+b[1]) && sqrt(a[2]*10+b[2]) == (int)sqrt(a[2]*10+b[2]) ) {
printf(\若三个新的数均是完全平方数,则输出 } } }
/* ———————————————-
分解三位数n的各位数字,将各个数字从高到低依次存入指针s
The possible perfect squares combinations are: 400 and 900 841 and 196 *思考题
求这样一个三位数,该三位数等于其每位数字的阶乘之和。 即 abc = a! + b! + c!
(正确结果:145 = 1! + 4! +5!)
24.阿姆斯特朗数
如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋性数)。
如 407=43+03+73就是一个阿姆斯特朗数。试编程求1000以内的所有阿姆斯特朗数。 *问题分析与算法设计
可采用穷举法,依次取1000以内的各数(设为i),将i的各位数字分解后,据阿姆斯特朗数的性质进行计算和判断。 *程序说明与注释 #include
int i,t,k,a[3];
printf(\than 1000:\\n\
for(i=2;i<1000;i++) /*穷举要判定的数i的取值范围2~1000*/ {
for(t=0,k=1000;k>=10;t++) /*截取整数i的各位(从高向低位)*/ {
a[t]=(i%k)/(k/10); /*分别赋于a[0]~a[2}*/ k/=10;
- 11 -
}
if(a[0]*a[0]*a[0]+a[1]*a[1]*a[1]+a[2]*a[2]*a[2]==i) /*判断i是否为阿姆斯特朗数*/
printf(\若满足条件,则输出*/ }
printf(\}
*运行结果
There are following Armstrong number smaller than 1000:
153 370 371 407 25.完全数 *问题分析与算法设计
按照亲密数定义,要判断数a是否有亲密数,只要计算出a的全部因子的累加和为b,再计算b的全部因子的累加和为n,若n等于a则可判定a和b是亲密数。计算数a的各因子的算法: 用a依次对i(i=1~a/2)进行模运算,若模运算结果等于0,则i为a的一个因子;否则i就不是a的因子。 *程序说明与注释 #include
int a,i,b,n;
printf(\–numbers pair smaller than 3000:\\n\
如果一个数恰好等于它的因子之和,则称该数为―完全数‖。 *问题分析与算法设计
根据完全数的定义,先计算所选取的整数a(a的取值1~1000)的因子,将各因子累加于m,若m等于a,则可确认a为完全数。 *程序说明与注释 #include
int a,i,m;
printf(\1000:\\n\
for(a=1;a<1000;a++) /*循环控制选取1~1000中的各数进行判断*/ {
for(m=0,i=1;i<=a/2;i++) /*计算a的因子,并将各因子之和m=a,则a是完全数输出*/ if(!(a%i))m+=i; if(m==a) printf(\}
printf(\}
*运行结果
TThere are following perfect numbers smaller than 1000: 6 28 496
26.亲密数
如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。
for(a=1;a<3000;a++) /*穷举1000以内的全部整数*/ {
for(b=0,i=1;i<=a/2;i++) /*计算数a的各因子,各因子之和存放于b*/
if(!(a%i))b+=i; /*计算b的各因子,各因子之和存于n*/ for(n=0,i=1;i<=b/2;i++) if(!(b%i))n+=i; if(n==a&&a
输出*/ } }
*运行结果
There are following friendly–numbers pair smaller than 3000:
220.. 284 1184.. 1210 2620.. 2924 27.自守数
自守数是指一个数的平方的尾数等于该数自身的自然数。例如: 252=625 762=5776 93762=87909376 请求出200000以内的自守数 *问题分析与算法设计
若采用―求出一个数的平方后再截取最后相应位数‖的方法显然是不可取的,因为计算机无法表示过大的整数。
分析手工方式下整数平方(乘法)的计算过程,以376为例: 376 被乘数 X 376 乘数 ———-
2256 第一个部分积=被乘数*乘数的倒数第一位 2632 第二个部分积=被乘数*乘数的倒数第二位 1128 第三个部分积=被乘数*乘数的倒数第三位 ———- 141376 积
本问题所关心的是积的最后三位。分析产生积的后三位的过程,可以看出,在每一次的部分积中,并不是它的每一位都会对积的
- 12 -
后三位产生影响。总结规律可以得到:在三位数乘法中,对积的后三位产生影响的部分积分别为:
第一个部分积中:被乘数最后三位*乘数的倒数第一位 第二个部分积中:被乘数最后二位*乘数的倒数第二位 第三个部分积中:被乘数最后一位*乘数的倒数第三位 将以上的部分积的后三位求和后截取后三位就是三位数乘积的后三位。这样的规律可以推广到同样问题的不同位数乘积。 按照手工计算的过程可以设计算法编写程序。 *程序说明与注释 #include
long mul,number,k,ll,kk;
*程序说明与注释
原程序好像有错,而且比较费解,现基于原程序修改如下(如果读者还发现错误请提出): #include
int m[16],n,i,t,count=0; long unsigned a,k;
printf(\for(n=1;n<256;n++) /*穷举n的取值范围*/ {
k=0;t=1;a=n*n; /*计算n的平方*/
printf(\than 200000:\\n\
for(number=0;number<200000;number++) {
for(mul=number,k=1;(mul/=10)>0;k*=10); /*由number的位数确定截取数字进行乘法时的系数k*/ kk=k*10; /*kk为截取部分积时的系数*/ mul=0; /*积的最后n位*/
ll=10; /*ll为截取乘数相应位时的系数*/ while(k>0) {
mul=(mul+(number%(k*10))*(number%ll-number%(ll/10)))%kk;
/*(部分积+截取被乘数的后N位*截取乘数的第M位),%kk再截取部分积*/
k/=10; /*k为截取被乘数时的系数*/ ll*=10; }
if(number==mul) /*判断若为自守数则输出*/ printf(\} }
*运行结果
It exsts following automorphic numbners smaller than 200000:
0 1 5 6 25 76 376 625 9376 90625 109376 28.回文数
打印所有不超过n(取n<256) 的其平方具有对称性质的数(也称回文数)。
*问题分析与算法设计
对于要判断的数n,计算出其平方后(存于a),将a的每一位进行分解,再按a的从低到高的顺序将其恢复成一个数k(如n=13,则a=169且k=961),若a等于k则可判定n为回亠数。
for(i=0;a!=0;i++) /*从低到高分解数a的每一位存于数组m[0]~m[16]*/ {
m[i]=a;//这个是取得a的个位,整个循环合起来就可以取得各个位 a/=10; } int j=0;
for(i–;j
if(m[j]!=m[i])break;//只要有一位不是对称,那就说明不是对称,就可以退出了
//所有的位都对称就说明是对称了,这样就可以打印出结果了 if(j>=i)printf(\} return 0; }
*运行结果
No. number it's square(palindrome) 1 1 1 2 2 4 3 3 9 4 11 121 5 22 484 6 26 676 7 101 10201 8 111 12321 9 121 14641 10 202 40804 11 212 44944
//下面程序是原来的,有错,而且费解 #include
- 13 -
{
int m[16],n,i,t,count=0; long unsigned a,k;
printf(\for(n=1;n<256;n++) /*穷举n的取值范围*/ {
k=0;t=1;a=n*n; /*计算n的平方*/
for(i=1;a!=0;i++) /*从低到高分解数a的每一位存于数组m[1]~m[16]*/ {
m[i]=a;//安安注:这个是取得a的个位,整个循环合起来就可以取得各个位,并存于数组中,为了是下面判断是不是对称 a/=10; *程序说明与注释 #include
int n,a,b; condition\\n\
for(n=1000;n<10000;n++) /*四位数N的取值范围1000~9999*/ {
a=n/100; /*截取N的前两位数存于a*/ b=n0; /*截取N的后两位存于b*/
if((a+b)*(a+b)==n) /*判断N是否为符合题目所规定的性质printf(\
}
for(;i>1;i–) {
k+=m[i-1]*t; t*=10; }
if(k==n*n)
printf(\} return 0; }
*运行结果
No. number it's square(palindrome) 1 1 1 2 2 4 3 3 9 4 11 121 5 22 484 6 26 676 7 101 10201 8 111 12321 9 121 14641
29.求具有abcd=(ab+cd)2性质的四位数
3025这个数具有一种独特的性质:将它平分为二段,即30和25,使之相加后求平方,即(30+25)2,恰好等于3025本身。请求出具有这样性质的全部四位数。 *问题分析与算法设计
具有这种性质的四位数没有分布规律,可以采用穷举法,对所有四位数进行判断,从而筛选出符合这种性质的四位数。具体算法实现,可任取一个四位数,将其截为两部分,前两位为a,后两位为b,然后套用公式计算并判断。
的四位数*/ printf(\} }
*运行结果
There are following numbers with 4 digits satisfied condition: 2025 3025 9801 30.求素数
求素数表中1~1000之间的所有素数 *问题分析与算法设计
素数就是仅能衩1和它自身整除的整数。判定一个整数n是否为素数就是要判定整数n能否被除1和它自身之外的任意整数整除,若都不能整除,则n为素数。
程序设计时i可以从2开始,到该整数n的1/2为止,用i依次去除需要判定的整数,只要存在可以整除该数的情况,即可确定要判断的整数不是素数,否则是素数。 *程序说明与注释 #include
int n1,nm,i,j,flag,count=0; do{
printf(\
scanf(\输入求素数的范围*/ }while(!(n1>0&&n1 printf(\\\n\if(n1==1||n1==2) /*处理素数2*/ { printf(\n1=3;count++; } for(i=n1;i<=nm;i++) /*判定指定范围内的整数是否为素数*/ - 14 - { if(!(i%2))continue; for(flag=1,j=3;flag&&j /*判定能否被从3到整数的一半中的某一数所整除*/ if(!(i%j))flag=0; /*若能整除则不是素数*/ if(flag) printf(++count?\} } *思考题 请找出十个最小的连续自然数,它们个个都是合数(非素数) if(i<=1)return 0; if(i==2)return 1; if(!(i%2))return 0; /*if no,return 0*/ for(j=3;j<=(int)(sqrt((double)i)+1);j+=2) if(!(i%j))return 0; return 1; /*if yes,return 1*/ } 32.可逆素数 求四位的可逆素数。可逆素数指:一个素数将其各位数字的顺序倒过来构成的反序数也是素数。 C/C++语言经典、实用、趣味程序设计编程百例精解(4) 31.歌德巴赫猜想 验证:2000以内的正偶数都能够分解为两个素数之和(即验证歌德巴赫猜想对2000以内的正偶数成立)。 *问题分析与算法设计 为了验证歌德巴赫猜想对2000以内的正偶数都是成立的,要将整数分解为两部分,然后判断出分解出的两个整数是否均为素数。若是,则满足题意;否则重新进行分解和判断。 程序中对判断是否为素数的算法进行了改进,对整数判断―用从2开始到该整数的一半‖改为―2开始到该整数的平方根‖。原因何在请自行分析。 *程序说明与注释 #include for(i=4;i<=2000;i+=2) { for(n=2;n printf(\若均是素数则输出*/ break; } if(n==i) printf(\} } int fflag(int i) /*判断是否为素数*/ { int j; *问题分析与算法设计 本题的重点不是判断素数的方法,而是求一个整数的反序数。 求反序数的方法是从整数的末尾依次截取最后一位数字,每截取一次后整数缩小10倍,将截取的数字作为新的整数的最后一位(新的整数扩大10倍后加上被截取的数字)。这样原来的整数的数字从低到高被不断地截取,依次作为新的整数从高到低的各位数字。 *程序说明与注释 #include int i,count; printf(\for(count=0,i=1001;i<9999;i+=2) //穷举全部的奇数 { if(num(i)) //若是可逆素数,则输出 printf(count%9 ? \ } return 0; } int num(int number) { int i,j; if(!ok(number))return 0; //判断是否为素数 for(i=number,j=0;i>0;i/=10) //按位将整数倒过来,产生反序数 { j=j*10 + i; } if(number if(!ok(i)) //判断对应的反序数是否为可逆素数 - 15 -