优美数式

本节探讨一类具有 趣味填数特性的数式——优美数式 ,之所以称为优美,是因为数式中各数字不重复出现;


优美和式

试把1,2,……,9这9个数字分别填入以下和式的9个口中,为体现优美,要求1~9这9个数字在式中出现一次且只出现一次,使得和式成立:

  • 口 口 口 + 口 口 口 = 口 口 口

约定以上和式左边的前3位数小于后3位数,且右边的和数相同的为同一和式,即要求所有和式的右边和不同;

搜索并输出所有9数字优美和式;

1.设计要点:

这是一道容易发生增解与遗解的填数趣题,要求填入每个数式的9个数字为1,2,……,9,既不遗漏,也不重复;

为操作方便,设置m数组存储和式中的3个数,即:m(1)+m(2)=m(3)

为不至于重复,设m(1)< m(2);设置m(3),m(1)循环,m(3)为外循环,每打印输出一个解即跳出,保证一个m(3)至多输出一个解,不至于输出右边相同的和式;

为判别是否优美,即是否寸在重复数字,把m(1)、m(2)、m(3)分离数字,并用f数组统计每个数字的个数(f(k)即数字k的个数,k=0,1,……,9)成立,即得没有重复数字的和式,即为优美和式,输出并用n统计解的个数;

2.程序设计:

#include<stdio.h>
int main()
{
   int n,x,y,t,k,m[4],f[11];
   printf("9数字优美和式:\n");
   n=0;
   for(m[3]=379;m[3]<=987;m[3]++)
      for(m[1]=123;m[1]<m[3]/2;m[1]++)  /*对m(3),m(1)实施枚举*/
      {
         m[2]=m[3]-m[1];
         for(k=0;k<=9;k++)
            f[k]=0;
         for(k=1;k<=3;k++)
         {
            y=m[k];
            while(y>0);      /*分离各数字用f数组统计*/
            {
               x=y%10;
               f[x]=f[x]=f[x]+1;
               y=y/10;
            }
         }
         for(t=0,k=1;k<=9;k++)
            if(f[k]!=1)
               t=1;          /*检验是否有重复数字*/
         if(t==0)            /*打印9数字优美和式*/
         {
            printf("%5d+%3d=%3d ",m[1],m[2],m[3]);
            n++;
            if(n%4==0)
               printf("\n");
            break;           /*对一个和数输出后即退出*/
         }
      }
   printf("\n共%d个\n",n);
}

3.程序运行示例及其注意事项:

9数字优美和式:
173+286=459  173+295=468  127+359=486  127+368=495
162+387=549  128+439=567  182+394=576  216+378=594
······
341+586=927  152+784=936  162+783=945  216+738=954
215+748=963  314+658=972  235+746=981
共31个

案例要求右边的和数相同的为同一和式,减少了重复,例如,当右边的和数为459时,由173+286=459,右边两数交换个位数字得176+283=459,交换十位数字183+276=459,这些交换造成的重复有损美感;

4.引申至10数字优美和式:

试把0,1,2,……,9这10个数字分别填人以下和式的10个口中,为体现优美,要求0~9这10个数字在式中出现一次且只出现一次,使得和式成立:

  • 口 口 口 + 口 口 口 = 口 口 口 口

约定以上和式中左边的前3位数小于后3位数,且右边的和数相同的为同一和式,即要求所有和式的右边和不同;

搜索并输出所有10数字优美和式;

(1)、设计要点:

为操作方便,设m(1)+m(2)=m(3),m(1)< m(2);

建立m(3)与m(1)循环:显然1023<=m(3)<1800,102<=m(1)< m(3)/2

由和式知m(2)=m(3)-m(1);

优美判别同上;

(2)、程序设计:

#include<stdio.h>
int main()
{
   int n,x,y,t,k,m[4],f[11];
   printf("10数字优美和式:\n");
   n=0;
   for(m[3]=1023;m[3]<=1802;m[3]++)
      for(m[1]=102;m[1]<m[3]/2;m[1]++)  /*对m(3),m(1)实施枚举*/
      {
         m[2]=m[3]-m[1];
         for(k=0;k<=9;k++)
            f[k]=0;
         for(k=1;k<=3;k++)
         {
            y=m[k];
            while(y>0)        /*分离各数字用f数组统计*/
            {
               x=y%10;
               f[x]=f[x]+1;
               y=y/10;
            }
         }
         for(t=0,k=0;k<=9;k++)
            if(f[k]!=1)
               t=1;           /*检验是否有重复数字*/
         if(t==0)             /*打印优美和式*/
         {
            printf("%5d+%3d=%4d  ",m[1],m[2],m[3]);
            n++;
            if(n%4==0)
               printf("\n");
            break;            /*对一个和数输出后即退出*/
         }
      }
   printf("\n共%d个\n",n);
}

(3)、程序运行示例及其注意事项:

10数字优美和式:
  437+589=1026    246+789=1035    264+789=1053    473+589=1062
  324+765=1089    342+756=1098    347+859=1206    426+879=1305
  624+879=1503    743+859=1602
共10个

以上两程序中的“break;”语句确保右边的和数相同只输出一个和式,请删除该语句后运行程序,会出现和数相同的多个和式,之所以约定“右边的和数相同的为同一和式”,就是起到一个精简作用;


优美综合式

本节设计构建一类优美综合数学式,这是一个有趣也有难度的填数游戏,数学式称为“优美”,是指各个数字在式中出现而不重复;数学式称为“综合”,是指该数学式中包含有加、减、乘、除与乘方运算;

1.案例提出:

把数字1,2,……,9这9个数字分别填入以下含加、减、乘、除与乘方(^,例2^3即为2^3)的综合运算式中的9个口中,使得该式成立:

  • 口^口 + 口口 ÷ 口 - 口口口 × 口 = 0

要求数字1,2,……,9这9个数字在式中出现一次且只出现一次,且约定数字“1”不能为一位数(即排除式中的各个1位数为1这一平凡情形);

2.按double型设计:

因式中出现乘方(a^b)运算,自然想到应用数据类型double进行设计;

(1)、设计要点:

设置f数组存储式中的9个数字,方便比较是否存在重复数字;

式中含有加、减、乘、除与乘方5种运算,应用枚举设计求解;

设式左的6个整数从左至右分别为a、b、z、c、d、e,即:

  • a^b+z/c-d*e=0

其中z为2位整数,d为3位数,a、b、c、e为大于1的一位整数;

设置a、b、c、d、e、z循环,其中设计z为c的倍数;

  • 1)、若等式不成立,即pow(a,b)+z/c!=d*e,则返回继续;

  • 2)、检测式中9个数字是否存在相同数字:对6个整数共9个数字进行分离,9个数字分别赋值给数组f[1]~f[9];连同附加的f[0]=0,共10个数字在二重循环中逐个比较:若存在相同数字,t=1,不作输出;若不存在相同,即式中9个数字为1~9不重复,保持标记t=0,则输出所得的优美综合运算式,并设置n统计解的个数;

(2)、程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   double a,b,c,d,e,z;
   int j,k,t,n,f[10];
   printf("口^口 + 口口 ÷ 口 - 口口口 × 口 = 0\n");
   n=0;
   for(a=2;a<=9;a++)
    for(b=2;b<=9;b++)
     for(c=2;c<=9;c++)
      for(z=2*c;z<=98;z=z+c)   /*各数实施枚举,确保z为c的倍数*/
       for(d=102;d<=987;d++)
        for(e=2;e<=9;e++)
        {
           if(z<10 || pow(a,b)+z/c!=d*e)
              continue;        /*检验等式是否成立*/
           t=0;
           f[0]=0;             /*9个数字赋给f数组*/
           f[1]=a;
           f[2]=b;
           f[3]=c;
           f[4]=e;
           f[5]=floor(z/10);
           f[6]=fmod(z,10);
           f[7]=floor(d/100);
           f[8]=fmod(d,10);
           f[9]=floor(fmod(d,100)/10);
           for(k=0;k<=8;k++)
              if(f[k]==f[j])    /*检验数字是否有重复*/   
              {
                 t=1;
                 break;
              }
           if(t==0)
           {
              n++;              /*输出一个解*/
              printf("%2d:%.0f^%.0f+%.0f/%.0f",n,a,b,z,c);
              printf("-%.0f*%.0f=0 \n",d,e);
           }
   }
}

(3)、程序运行示例及其注意事项:

口^口 + 口口 ÷ 口 - 口口口 × 口 = 0
1: 4^6+72/9-513*8=0
2: 5^4+78/6-319*2=0

以上所得两个数式中包含有加、减、乘、除与乘方5种运算,也包含0,1,2,……,9这10个数字,充分体现了数学式的形态优美与和谐美;

3.案例引申:

把以上综合运算式右边的“0”引申为一位参数f,即求解一下更一般的数学式:

  • 口^口 + 口口 ÷ 口 - 口口口 × 口 = f

设含乘方(a^b)、加、减、乘、除的综合运算式的右边为一位非负整数f,请把数字0,1,2,……,9这10个数字中不同与数字f的9个数字不重复填入式左边的9个口中(约定数字“1”“0”不出现在一位数中,且“0”不为整数首位),使得该运算式成立;

输入整数f(0<=f<=9),输出对应的综合运算式;

(1)、设计要点:

设置m数组存储式中除f之外的6个整数,g数组统计式中7个整数的10个数字的频数;

把所有变量简单设置为整型,其中乘方a^b用a自乘b次实现;

同样,设综合运算式为:

  • a^b+z/c-d*e=f

同样是枚举设计,这样处理,可省略z循环,同时省略z是否能被c整除,省略等式是否成立的检测;

计算z后,检测z是否为两位数,若计算所得z非两位数,则返回;

然后分别对7个整数进行数字分离,设置g数组对7个整数分离的共10个数字进行统计,g(x)即为数字x(0~9)的个数;

  • 若某一g(x)不为1,不满足数字0,1,2,……,9这10个数字都出现一次且只出现一次,标记t=1;

  • 若所有g(x)全为1,满足数字0,1,2,……,9这10个数字都出现一次且只出现一次,保持标记t=0,则输出所得的优美综合运算式;

(2)、程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   int a,b,c,d,e,f,k,t,n,x,y,z,m[7],g[11];
   n=0;
   printf("请输入式右边的数字f:");
   scanf("%d",&f);
   for(a=2;a<=9;a++)
    for(b=2;b<=9;b++)
     for(c=2;c<=9;c++)
      for(d=102;d<=987;d++)    /*实施枚举*/
       for(e=2;e<=9;e++)
       {
          for(t=1,k=1;k<=b;k++)
             t=t*a;            /*计算乘方a^b*/
          z=(d*e+f-t)*c;
          if(z<10 || z>98)
             continue;
          m[1]=a;
          m[2]=b;
          m[3]=c;
          m[4]=d;
          m[5]=e;
          m[6]=z;
          for(x=0;x<=9;x++)
             g[x]=0;
          g[f]=1;
          for(k=1;k<=6;k++)
          {
             y=m[k];
             while(y>0)
             {
                x=y%10;
                g[x]++;       /*分离数字给g数组统计*/
                y=y/10;
             }
          }
          for(t=0,x=0;x<=9;x++)
             if(g[x]!=1)      /*检验数字0~9各出现一次*/
             {
                t=1;
                break;
             }
          if(t==0)            /*输出一个解*/
          {
             n++;
             printf("%2d: %d^%d+%d/%d",n,a,b,z,c);
             printf("-%d*%d=%d \n",d,e,f);
          }
   }
   if(n==0)
      printf("无解! \n");
}

(3)、程序运行示例及其注意事项:

请输入式右边的数字f:6
 1: 2^9+80/5-174*3=6
 2: 5^4+18/9-207*3=6
 3: 9^3+50/2-187*4=6

注意:以上设计中应用a自乘b次实现a^b,这样处理是简便的,同时,应用g数组进行数字统计来检验是否存在有重复数字,检测手段颇为新颖

变通:把数字0,1,2,……,9这10个数字分别填入以下含加、减、乘、除与乘方的综合运算式中的10个口中(约定0、1不能为一位数,0不能为整数首位),请修改以上程序,使得下式成立:

  • 口^口 + 口口 ÷ 口 - 口口口 × 口 = 口口

请问:这一填数游戏共有多少种不同的填入法?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值