若正整数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的程序输出结果- -