逐位整除数
来源:互联网 发布:视上眼镜淘宝 编辑:程序博客网 时间:2024/05/17 23:20
逐位整除数是一类新颖有趣的整数;
定义n位逐位整除数:从高位开始,高1位能被1整除(显然),高2位能被2整除,……,以此类推,整个n位数能被n整除;
例如1024569就是一个7位逐位整除数,因为1024569能被7整除,高6位即102456能被6整除,高5位即10245能被5整除,……;
对指定的正整数n,搜索共有多少个不同的n位逐位整除数?存在n位逐位整除数的整数n是否有最大值?
试探索指定的n位逐位整除数,输出所有n位逐位整除数;
回溯设计
1.说明:
设置a数组,存放求解的逐位整除数的各位,a[1]存储最高位数字,a[2]存储次高位数字,……,a[n]存储n位数的个位数字;
在a数组中,数组元素a[1]为最高位,从1开始取值,显然能被1整除;a[2]从0开始取值,存放第2位数,前2位即a[1]*10+a[2]能被2整除;……
为了判别已取的 i 位数能否被i整除,设置 j 循环:
for(r=0,j=1;j<=1;j++){ r=r*10+a[j]; r=r%i;}
1)、若r=0,即该i位数能被i整除,取标志量t=0,此时有两个选择:
- 若已取了n位,则输出一个n位逐位整除数,最后一位增1后继续探索;
- 若找不到n位,则 i=i+1 继续探索下一位;
2)、若r!=0,即前i位数不能被i整除,取标志量t=1,此时a[i]=a[i]+1,即第i位增1后继续;
若增值至a[i]>9,则a[i]=0即该位清零后i=i-1迭代回溯到前一位,直到第1位增值超过9后退出循环结束;
该算法可探索并输出所有n位逐位整除数,用s统计解的个数,若s=0,说明没有找到n位逐位整除数,输出“无解”;
2.程序设计:
#include<stdio.h>int main(){ int i,j,n,r,t,s,a[100]; printf("逐位整除数n位,请确定n:"); scanf("%d",&n); printf("所求%d位逐位整除数:\n",n); for(j=1;j<=100;j++) a[j]=0; t=0;s=0; i=1;a[1]=1; while(a[1]<=9) { if(t==0&&i<n) i++; for(r=0,j=1;j<=i;j++) { r=r*10+a[j]; r=r%i; } if(r!=0) { a[i]=a[i]+1; /*余数r!=0时,a[i]增1,t=1*/ t=1; while(a[i]>9&&i>1) { /*回溯*/ a[i]=0; i--; a[i]=a[i]+1; } } else t==0; /*余数r=0时,t=0*/ if(t==0&&i==n) { s++; printf(" %d:",s); for(j=1;j<=n;j++) printf("%d",a[j]); printf("\n"); a[i]=a[i]+1; } } if(s==0) printf("没有找到!\n"); else printf("共以上%d个解。\n",s);}
3.程序运行示例及其注意事项:
逐位整除数n位,请确定n:25所求25位逐位整除数:1:3608528850368400786036725
注意:输入n>25时,无解。这说明逐位整除数位数的最大值为25;
之所以说逐位整除数位数的最大值为25,是因为在这唯一的25位逐位整除数后添加0~9中任何一个数字后变为26位整数都不能被26整除。也就是说,不存在26位(及其以上)逐位整除数;
请验证以上求得的25位逐位整除数是否满足逐位整除数的整数特性:数的高k位能被k整除,k=1,2,……,25;
递推设计
根据逐位整除数的递推特性,也可以应用递推设计来求解逐位整除数;
1.说明:
注意到逐位整除数的构造特点:n位逐位整除数的高n-1位是一个n-1位逐位整除数。因而可在每一个n-1位逐位整除数后加一个数字j(0~9),得到一个n位数。测试该n位数如果能被n整除,则得到一个n位逐位整除数;
递推基础为n=1位,显然有g=9个一位数j(1~9);
注意到逐位整除数的位数可能比较大,为了递推方便,设置两个二维数组:a(i,d)为k-1位的第i个逐位整除数的从高位开始第d(1~n-1)位数字,b(m,d)为递推得到k位的第m个逐位整除数的从高位开始第d(1~n)位数字;
完成从k-1位推出k位之后,需要把m赋值给g,把b数组赋值给a数组,为下一步递推做准备;
- 最后输出递推得到的n位逐位整除数的个数g及所有n位逐位整除数;
- 当递增至n位没有得到n位逐位整除数时(g=0),输出“无解!”后结束;
2.程序设计:
#include<stdio.h>int main(){ int d,g,i,j,k,m,n,r,a[3000][30],b[3000][30]; printf("请输入逐位整除数的位数n:"); scanf("%d",&n); g=9; /*递推基础:1位时赋初值*/ for(j=1;j<=g;j++) a[j][1]=j; for(k=2;k<=n;k++) /*递推位数k从2开始递增*/ { m=0; for(i=1;i<=g;i++) /*枚举g个k-1位逐位整除数*/ for(j=0;j<=9;j++) /*k位数的个位数字为j*/ { a[i][k]=j; for(r=0,d=1;d<=k;d++) /*检测k位数除k的余数r*/ { r=r*10+a[i][d]; r=r%k; } if(r==0) { m++; for(d=1;d<=k;d++) b[m][d]=a[i][d]; /*满足条件的k位数赋值给b数组*/ } } g=m; /*递推得g个k位逐位整除数*/ for(i=1;i<=g;i++) for(d=1;d<=k;d++) a[i][d]=b[i][d]; /*g个b数组向a数组赋值,准备下步递推*/ } if(g>0) /*输出n位的个数及每一个数*/ { printf("%d位逐位整除数共%4d个:\n",n,g); for(i=1;i<=g;i++) { printf(" %d:",i); for(d=1;d<=n;d++) printf("%d",a[i][d]); printf("\n"); } } else printf("无解!\n");}
3.程序运行示例及其注意事项:
请输入逐位整除数的位数n:2424位逐位整除数共 3个: 1:144408645048225636603816 2:360852885036840078603672 3:402852168072900828009216
注意:事实上,唯一的一个25位逐位整除数就是在以上第二个24位逐位整除数后加上一个数字“5”而成。而以上其他两个24位逐位整除数后加上任意一个数字后所得25位数都不能被25整除;(注意到本例n不可能大于25,在此范围内以上两个程序设计均能快速求得相应的解)
变通:修改算法,求解n位逐位整除数的个数f(n)的最大值;
- 逐位整除数
- 检测一个数能否被3整除----位运算
- 数的整除性质
- 数组-子数整除
- 自整除数
- 两个数整除求余
- nefu115数的整除性
- nefu116 数的整除性
- POJ 2699:自整除数
- 被 7 整除的数
- 被 5 整除的数
- 不能被整除的数
- 按位DP hdu3967一个数划成两部分,相加能被k整除的方法数。一个区间的数总的方法数
- 各位和整除数的问题
- 各位和整除数的问题
- 求两个数的整除余数
- 求两个数的整除余数
- 1089 不能被3整除的数
- SpringMVC 面试题目以及答案
- kurento 6.0安装测试
- error while loading shared libraries: libstdc++.so.6: wrong ELF class: ELFCLASS32
- $.getJSON()回调函数不起作用
- 关于webpack的那点事
- 逐位整除数
- MATLAB安装与激活详解
- eclipse.ini配置jdk实例
- Linux下基于vsftpd的FTP文件传输协议详解(附完整流程命令)
- SSH全注解-annotation详细配置
- M1卡操作
- 1-UML基础
- 索引
- R语言采用多元回归建模的基本步骤