同基因和式

同基因数是由同一批数字通过不同排列所得的位数相同的整数,因此同基因数又称为排列数;

例如,由1、0、2、2这4个数字通过不同排列组成的4位整数1022、1202、1220、2012、2021、2102、2120、2201、2210是同基因数,而0122实际上只是一个3位数,并不含“0”,与上述诸数不同基因;

本节探索一类涉及同基因数的新颖数式——同基因和式;

由十进制同基因整数u、v、s组成的和式u+v=s称为同基因和式;

例如,1089+8019=9018是一个4位同基因和式,49896+49968=99864是一个5位同基因和式;

同时为了消除一个n位同基因和式中的3个数尾部同时加一个“0”后成为n+1位同基因和式的近亲衍生现象(例如10890+80190=91080),要求同基因和式u+v=s中u、v的个位数字不能同时为“0”;

对于给定的整数n(2<=n<=9),搜索并输出所有n位同基因和式u+v=s(约定u<=v);

1.设计要点:

为便于比较和式中的u、v、s是否同基因,设置数组f、g、h分别统计这3个整数中的数字频数;

(1)、枚举循环设置

通过循环计算最小的n位整数t,然后设置n位加数u、v的枚举循环:

  • u:t~(10*t-1)/2(因v>=u,且s=u+v<10*t)

  • v:u~10*t-u-1(因s=u+v是n位数,即s<10*t)

当mod(u,10)=0 and mod(v,10)=0时,返回;

这样设计循环,可以确保u、v、s都是n位整数,且满足其中u、v的个位数字不同时为“0”,v>=u;

(2)、检测同基因

对所得3个n位整数u、v、s(分别赋值给d1、d2、d3,以保证分解数字时u、v、s不变),通过n次循环分离其n个数字c,并分别用数组f、g、h统计数字c的频数;

在j(0~9)循环中比较3数组的值,若f[j]!=g[j]或f[j]!=h[j],说明3个整数u、v、s中至少有一个数字不同,非同基因,返回;

若所检测的3个整数u、v、s是同基因,则输出一个n位同基因和式u+v=s,用w统计个数;

2.程序设计:

#include
int main()
{
   int b,c,j,k,n,w,f[10],g[10],h[10];
   long d1,d2,d3,t,u,v,s;
   printf("请输入位数:");
   scanf("%d",&n);
   w=0;
   for(t=1,k=1;k<=n-1;k++)
      t=t*10;              /*计算最小的n位整数t*/
   for(u=t;u<=(10*t-1)/2;u++)   /*枚举n位加数u、v*/
      for(v=u;v<=10*t-1-u;v++)
      {
         if(u%10==0 && v%10==0)
            continue;           /*消除近亲衍生现象*/
         s=u+v;
         d1=u;
         d2=v;
         d3=s;
         b=0;
         for(j=0;j<=9;j++)
            f[j]=g[j]=h[j]=0;
         for(j=1;j<=n;j++)
         {
            c=d1%10;f[c]++;d1=d1/10;
            c=d2%10;g[c]++;d2=d2/10;
            c=d3%10;h[c]++;d3=d3/10;
         }
         for(j=0;j<=9;j++)
            if(f[j]!=g[j] || f[j]!=h[j])
            {
               b=1;
               break;          /*检验u、v、s是否同基因*/
            }
         if(b==0)
         {
            w++;
            printf("%3d: %ld+%ld=%ld \n",w,u,v,s);
         }
      }
   printf("共有%d个%d位同基因和式\n",w,n);
}

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

请输入位数:4
  1: 1089+8019=9108
  2: 1089+8091=9180
  3: 1269+1692=2961
  ······
 23: 4896+4968=9864
 24: 4959+4995=9954
共有24个4位同基因和式

事实上,同基因和式可以突破“整数”的限制,即在同基因和式的u、v、s的相同位置加“小数点”后仍是同基因和式;

例如459.9+499.5=995.4 、49.59+49.95=99.54等显然为同基因和式;

程序的枚举搜索时间复杂度为10^2n,当n比较大时(如n>=6),搜索比较困难,降低算法的复杂度是一个艰难而有现实意义的课题;

4.p进制同基因和式:

下面拓广到一般p进制,试图在指定的p进制中搜索同基因和式;

由3个p(2<=p<=16)进制同基因整数u、v、s组成的和式u+v=s称为p进制同基因和式;

例如,1142+1214=2411是一个4位5进制同基因和式,14315+35114=51431是一个5位8进制同基因和式;

同时要求p进制同基因和式u+v=s中u、v的个位数字不能同时为“0”,以消除近亲衍生现象;

对于给定的正整数p(2<=p<=16)与位数n,搜索并输出所有n位p进制同基因和式u+v=s(约定u<=v);

(3)、设计要点

1)、设置4个数组;

字符型d数组存储p进制的字符可能的字符“0123456789ABCDEF”;

一维f、g、h数组统计u、v、s的各个数字的频数,以便比较是否同基因;当检测为同基因和式后,f、g、h数组记录u、v、s从个位开始的各个数字,以便借d数组输出;

2)、枚举循环设置;

通过循环计算最小的n位p进制整数t,然后设置n位加数u、v的枚举循环:

  • u:t~(p*t-1)/2(因v>=u,且s=u+v< p*t)

  • v:u~p*t-u-1(因s=u+v是n位数,即s< p*t)

当mod(u,p)=0 and mod(v,p)=0时,返回;

这样设计循环,确保u、v、s都是p进制n位整数,且满足其中u、v的个位数字不同时为“0”,v>=u;

3)、检测同基因

对所得3个p进制n位整数u、v、s(分别赋值给d1、d2、d3,以保证分解数字时u、v、s不变),在n次循环中通过除p取余分离其n个数字c,并分别用一维数组f、g、h统计数字c的频数,例如,若f[3]=2,即数字“3”有2个;

在j(0~p-1)循环中比较3数组的值,若f[j]!=g[j]或f[j]!=h[j],说明3个整数u、v、s中至少有一个数字不同,即非同基因,返回;

4)、输出p进制和式;

当检测同基因和式成立后,改变用f、g、h数组记录u、v、s的从个位开始的各个数字,例如,若f[3]=2,即u中从个位开始的第3个数字为2;

设置3个从高位j=n-1到低位j=0的循环,则借助字符数组d输出d输出p进制数u、v、s,连接成一个p进制n位同基因和式u+v=s,用w统计其个数;

(2)、程序设计:

#include
int main()
{
   int b,c,j,k,n,p,w,f[16],g[16],h[16];
   long d1,d2,d3,t,u,v,s;
   char d[]="0123456789ABCDEF";
   printf("确定p进制,请输入p:");
   scanf("%d",&p);
   printf("请确定位数n:");
   scanf("%d",&n);
   w=0;
   for(t=1,k=1;k<=n-1;k++)
      t*=p;                  /*计算最小的n位p进制整数t*/
   for(u=t;u<=(p*t-1)/2;u++)
      for(v=u;v<=p*t-u-1;v++)  /*枚举近亲衍生现象*/
      {
         if(u%p==0 && v%p==0)
            continue;        /*消除近亲衍生现象*/
         s=u+v;
         b=0;
         d1=u;
         d2=v;
         d3=s;
         for(j=0;j<=p-1;j++)
            f[j]=g[j]=h[j]=0;
         for(j=0;j<=n-1;j++)   /*分离并统计u、v、s的p进制各数字*/
         {
            c=d1%p;f[c]++;d1=d1/p;
            c=d2%p;g[c]++;d2=d2/p;
            c=d3%p;h[c]++;d3=d3/p;
         }
         for(j=0;j<=p-1;j++)   /*检验u、v、s是否同基因*/
            if(f[j]!=g[j] || f[j]!=h[j])
            {
               b=1;
               break;
            }
         if(b==0)
         {
            d1=u;d2=v;d3=s;
            for(j=0;j<=n-1;j++)  /*分离并记录u、v、s的p进制各数字*/
            {
               c=d1%p;f[c]++;d1=d1/p;
               c=d2%p;g[c]++;d2=d2/p;
               c=d3%p;h[c]++;d3=d3/p;
            }
            w++;
            printf("%d: ",w);
            for(j=n-1;j>=0;j--)   /*借助d数组输出同基因和式u+v=s*/
               printf("%c",d[f[j]]);
            printf("+");
            for(j=n-1;j>=0;j--)
               printf("%c",d[g[j]]);
            printf("=");
            for(j=n-1;j>=0;j--)
               printf("%c",d[h[j]]);
            printf("\n");
         }
      }
   printf("共有%d个%d进制%d位同基因和式 \n",w,p,n);
}

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

确定p进制,请输入p:16
请确定位数n:3
1: 200+200=200
2: 200+200=200
3: 000+000=000
4: 000+000=000
共有4个16进制3位同基因和式

设置数组f、g、h前后二用是本程序的一个特点;

以上所得16进制和式“78F+7F8=F87”简洁而优美,单纯靠想象是很难奏效的,程序设计可以发现与揭示出许多的神奇与美;

程序的时间复杂度高达p^2n,当n比较大时,运行时间比较长;

例如,搜索“7F8F+7FF8=FF87”等34个16进制4位同基因和式时花费数分钟,降低同基因和式算法的时间复杂度是非常必要的;

你可能感兴趣的:(致美C程序,数式构建)