求出不超过n的幸运数
来源:互联网 发布:微电影制作软件 编辑:程序博客网 时间:2024/05/18 18:42
题目描述:
对于某一个数m,如果它只包含数字4或者7(如44,47,77),我们称之为幸运数。现在输入一个自然数x,求出不超过x的幸运数的个数。
注意:结果可能非常大,请将答案除10^9+7取余数。
思路一:
1. 引入队列queue,开始时将4,7入队。2. while(queue.peek() <= x) 则将queue头部元素top出队,并且将top*10+4和top*10+7入队 count++; 这样形成数字序列:4,7,44,47,74,77,444,447...3. 当2跳出循环时,return count;
算法有点思路简单,但是每出队一个数,将入队两个数,空间复杂度高。
思路二:
可以发现:
不考虑x数值大小,x位数与幸运数的个数关系如下:位数 幸运数个数 可能值 1 2 4,72 2+4=6 4,7,44,47,74,773 2+4+8=14 4,7,44,47,74,77,444,...,777...n 2+4+8+...+2^n = 2^(n+1)-2
尝试用动态规划求解。
1. 如果x有len位数,那么对于1~(m-1,m)~len而言,假定m-1处有pre个幸运数,m处有cur个幸运数,如上图所示。2. 那么针对Xm数值,分类考虑:if (Xm < 4) cur = 2^m - 2;else if (Xm == 4) /** *比如:Xm=4,XmXm-1Xm-2...X1 *(1)4Xm-1Xm-2...X1为幸运数的情况(与Xm-1Xm-2...X1为幸运数的情况相同);pre *(2)m-1位数中幸运数的个数:2^m - 2 *(3)将(1)和(2)合并,需要注意的是,两者有一部分幸运数是相同的,因此需要减去相同幸运数的个数2^(m-1) - 2 */ cur = pre - [2^(m-1) - 2] + [2^m - 2] cur = pre + 2^(m-1);else if (4 < Xm && Xm < 7) cur = pre + [2^(m+1) - 2] - 4 /** *同 Xm == 4的情况类似。 *比如:Xm=7,XmXm-1Xm-2...X1 *(1)7Xm-1Xm-2...X1为幸运数的情况(与Xm-1Xm-2...X1为幸运数的情况相同);pre *(2)499...9(m-1个9)内幸运数的个数:2 *(2^m - 2)- [2^(m-1) - 2] *(3)将(1)和(2)合并,需要注意的是,两者有一部分幸运数是相同的,因此需要减去相同幸运数的个数2^(m-1) - 2 */else if (Xm == 7) cur = pre + 2 *(2^m - 2)- [2^(m-1) - 2] -[2^(m-1) - 2] cur = pre + 2^melse cur = 3 * (2^m - 2)从1~m循环上述过程,并更新prepre = curreturn pre
有了上述关系式,写出代码如下:
/** * Author: Mengjun Li * Date: 2017/10/14 下午9:06 * Description:只含4or7的数字称为幸运数,给定一个数n,求出不超过n的幸运数的个数 *//** * @author Mengjun Li * @create 2017/10/14 * @since 1.0.0 */public class Main2 { public static void main(String[] args) { int x = 4; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 77; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 100; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 444; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 777; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 888; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); x = 21857711; System.out.println("不超过" + x + "的幸运数的个数: " + cal(x)); } public static int cal(int num) { //为了便于对num的每一个位进行操作,将其转化为String对象 String str = String.valueOf(num); int len = str.length(); int pre, cur = 0; if (str.charAt(len - 1) < '4') pre = 0; else if (str.charAt(len - 1) < '7') pre = 1; else pre = 2; int index = len - 2, tmp = 0; final int div = (int) (Math.pow(10,9)+7); while (index >= 0) { tmp = str.charAt(index) - '0'; if (tmp < 4) cur = (1 << len - index) - 2; else if (tmp == 4) cur = pre + (1 << len - index - 1); else if (tmp < 7) cur = (1 << len - index + 1) - 4; else if (tmp == 7) cur = pre + (1 << len - index); else cur = (1 << len - index + 1) - 2; index--; pre = cur % div; } return pre; }}
输出如下:
不超过4的幸运数的个数: 1不超过77的幸运数的个数: 6不超过100的幸运数的个数: 6不超过444的幸运数的个数: 7不超过777的幸运数的个数: 14不超过1000的幸运数的个数: 14不超过21857711的幸运数的个数: 254
阅读全文
0 0
- 求出不超过n的幸运数
- 求不超过N的正整数中因子最多的数
- 打印所有不超过n(n<256)的,其平方具有对称性质的数。
- 将n划分成最大数不超过m的划分数
- 求出1…n之间的所有亲和数
- 求出1…n之间的所有亲和数
- 面试算法题:求出所有N位的二进制数
- 特别的幸运数
- 打印所有不超过n(n<256)的其平方具有对称性的数(也称回文数)
- 打印所有不超过n(n<256)的,其平方具有对称性质的数,如11*11=121.
- 每日一题:给定n, 求出小于n的所有数中1的位数
- 输出不超过n的所有素数 (筛法)
- 1297 特别的幸运数
- 言的幸运数 swun1701
- 求不超过四位数的反序数
- poj 2378 Tree Cutting(树形DP,删点使得独立的部分结点数不超过n/2)
- 给定两个数m,n,使用欧几里得的辗转相除法求出它们的最大公约数
- hdu1715(给出n求出第n个斐波那契数)
- Java集合面试问题
- C语言——【复习提纲】1.数据类型
- selenium自动化学习之弹出框
- 基于UDP的socket编程
- Python Flask 6.0.1 工厂函数
- 求出不超过n的幸运数
- Python Flask 6.0.2 相对路径
- ubuntu14.04+opencv 3.1+contrib安装及测试
- HDU5044【LCA+差分】
- 笔试_oracle(8)
- python3中使用map,reduce和filter
- Python Flask(六) 大型网站架构
- win7如何设置电脑定时关机
- HDU