幸运数4&7:给定正整数n,求不大于n的仅由4和7组成的数字的个数

来源:互联网 发布:lbp算法matlab 编辑:程序博客网 时间:2024/05/16 14:16

 题目描述:我们称一个十进制正整数是幸运数当且仅当它只由数字4和7构成。现在给出一个正整数n,你需要计算由多少个不大于n的幸运数,由于答案可能非常大,你只需要输出答案除以1000000007后的余数。

输入:第一行包含一个整数n,1<=n<=10^100000

输出:输出对应的答案

测试样例:

125

6


21857711

254


朴素思路:逐个穷举

结果:超时,因为数目过大

思路受某位不知道姓名的大神指点,在此表示十分感谢O(∩_∩)O谢谢,思路说明:

符号说明:下面符号中,7xx表示x为4、或7,即744,777,747,774,共有2^2中可能性满足题意。

思路:由于数字仅由7、4组成,所以把满足要求的数字看做由7、4组成的“二进制”数字(7->1,4->0),这样当输入数字长度为n时,最少有种情况。

例如:441,,444,777,123,731,491,594,982,长度均为3,则最少的数目为6,分别是4,7,44,47,74,77。所以,需从最高位开始向右扫描,诸位判断情况:

case1:当前位置>7,说明此位置为7或4均可满足题意(例如982,那么7xx,4xx型均满足答案;),所以答案增加2^(n-i),i为当前位置下标(例如491,i=1时,9>7,那么47x,44x均满足要求,所以答案增加2^(3-1)=4种), 并且不用再向后判断。(因为从上例子可知后续结果已被包括,因为491>4xx)

case2: 当前位置==7,说明此位置为4可满足题意(例如777,那么4xx一定满足答案;731,那么4xx一定满足答案)但对于7xx是否满足,仍需继续扫描下一位判断;如果是最后一位为7,则最后一位7或4均满足答案,答案+2(如777,i=0,4xx满足;i=1,*4x满足;i=3,因为是最后一位,所以可以判断777,774满足条件,答案+2)

case3: 7>当前位置>4,说明此位置为4可满足题意(例如594,那么4xx一定满足,且594>4xx所以后续不用在判断,已经包含).

case4: 当前位置==4,类似于==7的情况,只不过不继续向后扫描,无法准确判断(由于441等情况的存在),但是当可以扫描至最后一位且最后一位为4时(例如444),则证明44...4情况可以存在,答案+1(例如444,在xx的情况下答案再加上444这一种情况)

case5:非4非7,不满足要求,停止扫描,把之前最扫描结果返回即可(如441,只有xx满足;123,只有xx满足;)




程序说明:因为10^100000 大概等于 4^160000(可取对数大概估算一下),所以预分配160000内存



import java.util.Scanner;public class LuckNum_4And7 {public static void main(String[] args){//输入n<=10^100000 约等于 4^160000 ,可以取对数算一下int[] Bit = new int[160000];int[] Sum = new int[160000];Bit[0] = 1 ;//2^0 = 1Sum[0] = 0 ;//Sum[0] = Bit[0]for(int i = 1;i<100010;i++){//初始化,把2的幂以及求和预先算一下,方便使用Bit[i] = Bit[i-1]*2%(1000000007);Sum[i] =( Sum[i-1] +Bit[i])%(1000000007);}Scanner sc = new Scanner(System.in);while(sc.hasNext()){String N = sc.nextLine();int lenth = N.length();int ans = Sum[lenth-1];//最短长度,例如:143,长度为三位,所以两位的长度一定满足for(int i=0;i<lenth;i++){//从最高位开始判断,判断712,741,474,444,447,132等几种情况if(N.charAt(i)>'7'){//当前位置大于头,以三位为例,如712,那么4xx的情况(x=4、7)均满足,那么两位xx的情况ans已求得,第三位又添加7、4两种情况ans += Sum[lenth-i];break;//之后全部满足,所以不用再往后按位检查}else if(N.charAt(i)<'7'&&N.charAt(i)>'4'){//当前位==7,那么当前位为4的情况一定可以通过,当前为7的可能性还须继续向下判断,所以结果累加上4xx的情况ans =(ans+Bit[lenth-i-1])%(1000000007);;break;//因为是4xx,之后全部满足,所以不用再往后按位检查}else if(N.charAt(i)=='7'){ans =(ans+ Bit[lenth-i-1])%(1000000007);;//因为为最后一位时,加的是bit[0]=1,但最后一位为7时 应包含两种情况xx7和xx4,所以再加1//if(i==lenth-1) ans++;}else if(N.charAt(i)=='4'){if(i==lenth-1) ans=(ans+1)%(1000000007);;}else{break;//此路不通}}System.out.println(ans);}}}




阅读全文
1 0