守形数

若正整数n是它平方数的尾部,则称n为守形数,又称同构数

例如,6是其平方数36的尾部,76是其平方数5776的尾部,6与76都是守形数;

探讨搜索指定区间内的守形数,进而搜索指定n位守形数;

区间守形数

试探求指定区间 [x,y] 内的所有守形数;

1.说明:

对指定区间 [x,y] 内的每一个整数a(约定a>1),求出其平方数s;
计算a的位数w,同时计算 b=10^w,a的平方s的尾部 c=s%b
比较整数a与其平方数的尾部c,若a=c,则输出守形数;

2.程序设计:

#include<stdio.h>
int main()
{  
   long a,b,c,k,m,s,x,y;
   printf("请输入区间的上下限整数x,y:");
   scanf("%ld,%ld",&x,&y);
   m=0;
   for(a=x;a<=y;a++)
   {
      s=a*a;    /*计算a的平方数s*/
      b=1;k=a;
      while(k>0)
      {
         b=b*10;
         k=k/10;
      }
      c=s%b;   /*c为a的平方数s的尾部*/
      if(a==c)
      {
         m++;
         printf("%ld^2=%ld \n",a,s);
      }
   }
   printf("区间[%ld,%ld]中,共以上%ld个守形数。\n",x,y,m);
}

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

请输入区间的上下限整数x,y:10,10000
25^2=625
76^2=5776
376^2=141376
625^2=390625
9376^2=87909376
区间[10,10000]中,共以上5个守形数。

n位守形数

以上程序设计搜索到 2个 2位守形数、2个 3位守形数、1个 4位守形数,守形数的个位数字为“5”或“6”;

试探索一般n位守形数;

1.说明:

为了求更多位数的守形数,可应用守形数的性质:一个m位守形数的尾部k(1<=k<=m-1)位数也是一个高位可能为“0”的守形数

道理很简单:a是一个m位数,a的平方数尾部的k位仅由a的尾部k位决定而与a的其他位无关

实施易知一位守形数有3个:1、5、6,则二位守形数的个位数字只可能是1、5、6这三个数字,根据这一思路,我们可应用递推求解;

设置数组 a[k] 存储守形数的第k位:守形数的个位数字a[1]选取d(1~9),a[k](k>1)选取j(0~9),同时设置b数组存储计算平方的中间值,设置c数组存储计算守形数的平方值,利用 “竖式乘模拟” 计算平方数;
通过比较若有 a[i]=c[i](i=1,2,……,k)成立,则k位守形数确立,继续递推下一位,直至n位打印输出;

2.程序设计:

#include<stdio.h>
int main()
{
   int n,d,k,j,i,t,m,w,z,u,v,a[500],b[500],c[500];
   printf("请输入整数n:");
   scanf("%d",&n);
   for(d=1;d<=9;d++)
   {
      for(k=1;k<=499;k++)
      {
         a[k]=0;
         b[k]=0;
         c[k]=0;
      }
      a[1]=d;  /*给守形数个位数赋值*/
      for(k=2;k<=n;k++)
      {
         for(j=0;j<=9;j++)
         {
            a[k]=j;  /*探索守形数的第k位a(k)选数字j*/
            v=0;
            for(i=1;i<=k;i++)
               c[i]=0;
            for(i=1;i<=k;i++)
            {
               for(z=0,t=1;t<=k;t++)
               {
                  u=a[i]*a[t]+z;
                  z=u/10;
                  b[i+t-1]=u%10;  /*计算中间结果存于b数组*/
               }
               for(w=0,m=i;m<=k;m++)
               {
                  u=c[m]+b[m]+w;  /*计算平方存于c数组*/
                  w=u/10;
                  c[m]=u%10;
               }
            }
            for(i=1;i<=k;i++)
               if(a[i]!=c[i]) /*出现不同数字时继续,a[k]选下一个数字*/
                  v=1;
            if(v==0)
               break;
         }
      }
      if(v==0&&a[n]!=0)  /*输出n位守形数结果*/
      {
         printf("%d结尾的%d位守形数:",a[1],n);
         for(k=n;k>=1;k--)
            printf("%d",a[k]);
         printf("\n");
      }
   }
}

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

请输入整数n:30
5结尾的30位守形数:106619977392256259918212890625
6结尾的30位守形数:893380022607743740081787109376

注意:以上结果中“5结尾的30位守形数”的第29位为“0”,如果输入n=29,程序运行结果中就没有5结尾的29位守形数。事实上“29位守形数”是存在的,只是其最高位为“0”而已。

  • 变通:

更为明确地刻画出递推进程,建议把以上程序中“输出n位守形数结果”改为“输出k位守形数结果”,即在k循环内加入以下输出程序段:

if(v==0&&a[k]!=0)  /*输出k位守形数结果*/
{
   printf("%d结尾的%d位守形数:",a[1],k);
   for(j=k;j>=1;j--)
      printf("%d",a[j]);
   printf("\n");
}

请观察对应n=30的程序输出结果- -

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值