然后分别对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) 程序实现 // 四则运算式 #include
{int x,y,t,k,a,b,c,d,e,n=0; int m[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;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(\
} }
printf(\ }
2-8 合数世纪探求
定义一个世纪的100个年号中不存在一个素数,即100个年号全为合数的世纪称为合数世纪。
探索最早的合数世纪。 (1) 设计要点
应用穷举搜索,设置a世纪的的50个奇数年号(偶数年号无疑均为合数)为b,用k试商判别b是否为素数,用变量s统计这50个奇数中的合数的个数。
对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为最早的合数世纪,打印输出后退出循环结束。
(2) 合数世纪程序设计 // 合数世纪探求 #include
{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;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\
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
{ long c,d,f,m,j; int t,n;
printf(\求最小的n个连续合数.\\n\ printf(\请输入n:\ scanf(\ 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个连续合数区间为:\ printf(\。 \\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-7 9数字三角形
(1)求解要点。
把和为s的9个正整数存储于b数组b(1),…,b(9)中,分布如下图所示。为避免重复,不妨约定三角形中数字“下小上大、左小右大”,即b(1)
图2-8 b数组分布示意图
可以根据约定对b(1)、b(7)和b(4)的值进行循环探索,设置: b(1)的取值范围为1~(s-21)/3(因其他6个数之和至少为21)。 b(7)的取值范围为b(1)+1~(s-28)/2。 b(4)的取值范围为b(7)+1~(s-36)。 同时探索判断步骤如下:
1)若(s+b(1)+b(7)+b(4))%3≠0,则继续探索;否则,记s1=(s+b(1)+b(7)+b(4))/3。 2)根据约定对b(3)、b(5)和b(8)的值进行探索,设置: b(3)的取值范围为(s1-b(1)-b(4))/2+1~s1-b(1)-b(4)。 b(5)的取值范围为(s1-b(4)-b(7))/2+1~s1-b(4)-b(7)。 b(8)的取值范围为(s1-b(1)-b(7))/2+1~s1-b(1)-b(7))。 同时根据各边之和为s1,计算出b(2)、b(6)和b(9): b(2)=s1-b(1)-b(4)-b(3) b(6)=s1-b(4)-b(5)-b(7) b(9)=s1-b(1)-b(7)-b(8)
3)若b数组存在相同正整数,则继续探索。
4)设s2=b(1)*b(2)*b(3)*b(4),若另两边之积不为s2,则继续探索;否则探索成功,打印输出结果,接着继续探索直到所有数字组探索完毕为止。 (2)9数字三角形求解程序设计。
// 9数字三角形求解 #include
int k,j,t,s,s1,s2,n,b[10]; printf(\请输入正整数s:\ scanf(\ n=0;
for(b[1]=1;b[1]<=(s-21)/3;b[1]++)
for(b[7]=b[1]+1;b[7]<=(s-28)/2;b[7]++) for(b[4]=b[7]+1;b[4]<=s-36;b[4]++) {
if((s+b[1]+b[4]+b[7])%3!=0) continue; s1=(s+b[1]+b[4]+b[7])/3;
for(b[3]=(s1-b[1]-b[4])/2+1;b[3] b[2]=s1-b[1]-b[4]-b[3]; b[6]=s1-b[4]-b[7]-b[5]; b[9]=s1-b[1]-b[7]-b[8]; t=0; for(k=1;k<=8;k++) for(j=k+1;j<=9;j++) if(b[k]==b[j]) {t=1;k=8;break;} if(t==1) continue; s2=b[1]*b[2]*b[3]*b[4]; if(b[4]*b[5]*b[6]*b[7]!=s2) continue; if(b[1]*b[9]*b[8]*b[7]!=s2) continue; n++; printf(\:-\ for(k=2;k<=9;k++) printf(\ printf(\ } } printf(\共%d个解。\}