双码二部数序列
来源:互联网 发布:网络流行语网站 编辑:程序博客网 时间:2024/04/28 18:47
双码二部数定义:由两个不同数码组成,每个数码多于1位时相连而不分开的正整数称为双码二部数,其中处于高位相连数字称为高部,处于低位相连数字称为低部;
例如330是一个3位双码二部数:高部数字为3,高部位数为2;低部数字为0,底部位数为1,而333只有一个数码,4407有三个数码,4474的数码4呈分开状态,都不是双码二部数;
试统计n位双码二部数的个数,并求出n位双码二部数从小到大排序序列的第m项;
输入正整数n(1< n< 10000)与m,输出n位双码二部数的个数,同时输出n位双码二部数序列的第m项的高部数字(高部位数)和低部数字(底部位数),如果m大于n位双码二部数的个数,则输出“0”;
1.递增枚举要点:
设n(n>1)位双码二部数为a……ab……b(1<=a<=9,0<=b<=9),其高部数字a有la位,低部数字b有lb位,显然有:
- la+lb=n (1<=la<=n-1)
为了确保从小到大枚举双码二部数,要注意枚举循环的先后次序:首先,高部数字a必须从小到大,范围为1~9;当a确定后,高部位数la简单地从小到大或从大到小都不能确保双码二部数从小到大变化,需要配合b分以下3步完成,为便于理解,以n=4,a=4的递增进程实施标注;
(1)、la增长(1~n-2)段,lb=n-la,b递增(0~a-1)取值;
4000 4111 4222 4333 (la=1, lb=3, b: 0~3)4400 4411 4422 4433 (la=2, lb=2, b: 0~3)
(2)、la与lb取定值段,la=n-1,lb=1,b递增(0~9)取值(当b=a时跳过);
4440 4441 4442 4443 4445 4446 4447 4448 4449 (la=3, lb=1, b: 0~9, 其中b=4时跳过)
(3)、la减小(n-2~1)段,lb=n-la,b递增(a+1~9)取值;
4455 4466 4477 4488 4499 (la=2, lb=2, b: 5~9)4555 4666 4777 4888 4999 (la=1, lb=3, b: 5~9)
以上3步骤中每一步骤都是递增的,且3个步骤衔接中没有重复与遗漏,从而可能确保n位的双码二部数从小到大递增,没有重复与遗漏;
2.枚举程序设计:
#include<stdio.h>#include<math.h>int main(){ int a,b,a0,b0,n,la,lb,la0; long m,s; printf("请输入整数n,m: "); scanf("%d,%ld",&n,&m); s=0; for(a=1;a<=9;a++) /*高部数字a从小到大枚举*/ { for(la=1;la<=n-2;la++) /*高部数字la分3个步骤枚举*/ { lb=n-la; for(b=0;b<=a-1;b++) { s++; /*变量s统计个数*/ if(s==m) /*记录第m个数的信息*/ { a0=a; b0=b; la0=la; } } } la=n-1; lb=1; for(b=0;b<=9;b++) { if(a!=b) /*当a=b时跳过*/ { s++; if(s==m) { a0=a; b0=b; la0=la; } } } for(la=n-2;la>=1;la--) { lb=n-la; for(b=a+1;b<=9;b++) { s++; if(s==m) { a0=a; b0=b; la0=la; } } } } if(s>=m) printf(" %ld,%d(%d)%d(%d)\n",s,a0,la0,b0,n-la0); else printf(" %ld,%d\n",s,0);}
3.简化枚举循环设计:
#include<stdio.h>int main(){ int a,b,a0,b0,n,la,la0; long m,s; printf("请输入整数n,m: "); scanf("%d,%ld",&n,&m); s=1; a=1; b=0; la=1; /*默认n位第1个为1后n-1个0*/ while(la<n-1 || a<9 || b<8) { s++; if(b==9) /*此时b不能增1,有以下两种选择*/ if(la==1) /*①a增1后,b从0开始*/ { a++; b=0; } else /*②a段长增1后,b从a+1开始*/ { la--; b=a+1; } else if(b!=a-1) /*a与la不变,b增1*/ b++; else if(la!=n-1) /*a段长增1后,b从0开始*/ { la++; b=0; } else if(b<8) /*b增2跳过a=b情形*/ b+=2; if(s==m) { a0=a; b0=b; la0=la; } } if(s>=m) printf(" %ld,%d(%d)%d(%d)\n",s,a0,la0,b0,n-la0); else printf(" %ld,%d\n",s,0);}
4.程序运行示例及其注意事项:
请输入整数n,m: 40,20173159,6(30)7(10)
可知40位双码二位数共有3159个,40位双码二部数升序序列的第2017项高部30个“6”,低部10个“7”;
由第2017项的数据看似非常大,但枚举次数只有3159次;
枚举循环次数即n为双码二部数的个数,随着n的增大运算显著增长,但对于n<10000,枚举时间是可以接受的;
双码二部数的递增枚举是比较复杂的,也容易出错,这一设计提醒我们不要轻视枚举,枚举设计可以解决一些较为复杂的搜索案例;
- 双码二部数序列
- 二部图
- 序列数交换法
- 计算二进制序列数
- 求序列逆序数
- 求序列逆序数
- P数序列
- 组合数 序列
- 二部图(染色法判断二部图)
- 获取36位进制序列数
- 求斐波拉契序列和回文数
- 最大回文子序列数
- nefu1037回文子序列数
- HPU OJ 序列找数
- 【HPU】[1728]序列找数
- catalan数 出栈序列
- 序列数索引(排序索引)
- 10:找最大数序列
- [简化代码] -- 我们要惜字如金
- Git详解之一 Git起步
- js 延迟事件加载
- android代码混淆
- SpringBoot -- 服务注册与发现
- 双码二部数序列
- 《印象笔记留给你的空间》第1章 建立思维的秩序 / 第2章 建立信息的秩序
- 1月12日中软的第一天
- H5 本地存储学习笔记
- POJ 3292Semi-prime H-numbers(数论)
- 【Hibernate】初遇Hibernate
- javascript栈
- 打工仔:如何来做微创业
- Java BIO、NIO、AIO 学习