hdu 5676 ztr loves lucky numbers(dfs+离线)

Problem Description

ztr loves lucky numbers. Everybody knows that positive integers are lucky if their decimal representation doesn‘t contain digits other than 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.

Lucky number is super lucky if it‘s decimal representation contains equal amount of digits 4 and 7. For example, numbers 47, 7744, 474477 are super lucky and 4, 744, 467 are not.

One day ztr came across a positive integer n. Help him to find the least super lucky number which is not less than n.

Input

There are T(1≤n≤105) cases

For each cases:

The only line contains a positive integer n(1≤n≤1018). This number doesn‘t have leading zeroes.

Output

For each cases
Output the answer

Sample Input

2
4500
47

Sample Output

4747
47

直接暴力显然TLE,考虑按位DFS

每一位只可能是4或7

所以根据这个来DFS即可,时间复杂度O(T*2^{log_{10}n})O(T∗2?log?10??n??)

考虑到T特别大,不可能每次都DFS

而经过计算,2^{18}=2621442?18??=262144,所以全部储存下来

对于每次询问,二分即可

考虑一个边界条件,即当结果爆ll怎么办?

即答案应当为10个4、10个7的时候,显然unsigned long long也不行

那么只能采用特判了

首先,由于每一位只能是4或7,且
2^{18}=2621442?18??=262144,故而考虑离线打表,即利用dfs求解出所有只含数字4和7,且4和7数量相等的数

1 void dfs(ll sum,int c1,int c2){
2    if(c1>=k1 && c2>=k2){
3       ans[num++]=sum;
4       return;
5    }
6    if(c1<k1) dfs(sum*10+4,c1+1,c2);
7    if(c2<k2) dfs(sum*10+7,c1,c2+1);
8 }

结果存储在ans数组中,此时可以得到符合条件的数有66196+1个,而数据有T组,好吧,那就二分查找

1 int cnt = lower_bound(ans,ans+num,n)-ans;

需要注意的一点是,当n>777777777444444444的时候,18位数里面已经没有比这更大的符合条件的数了,那么只能特判一下,解为最小的20位符合条件的数,即44444444447777777777

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 #define ll long long
 6 #define N 1000000
 7 int k1,k2;
 8 ll ans[N];
 9 int num;
10 ll n;
11 void dfs(ll sum,int c1,int c2){
12    if(c1>=k1 && c2>=k2){
13       ans[num++]=sum;
14       return;
15    }
16    if(c1<k1) dfs(sum*10+4,c1+1,c2);
17    if(c2<k2) dfs(sum*10+7,c1,c2+1);
18 }
19 void init(){
20    num=0;
21    for(int i=2;i<=18;i+=2){
22       k1=k2=i/2;
23       dfs(0,0,0);
24    }
25 }
26 int main()
27 {
28     init();
29     int t;
30     scanf("%d",&t);
31     while(t--){
32         scanf("%I64d",&n);
33         int cnt = lower_bound(ans,ans+num,n)-ans;
34         if(cnt<num){
35            printf("%I64d\n",ans[cnt]);
36         }else{
37            printf("44444444447777777777\n");
38         }
39     }
40     return 0;
41 }
时间: 2024-10-27 05:54:19

hdu 5676 ztr loves lucky numbers(dfs+离线)的相关文章

hdu 5676 ztr loves lucky numbers(BC——暴力打表+二分查找)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5676 ztr loves lucky numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 594    Accepted Submission(s): 257 Problem Description ztr loves luck

hdu 5676 ztr loves lucky numbers

题目链接:hdu 5676 一开始看题还以为和数位dp相关的,后来才发现是搜索题,我手算了下,所有的super lucky number(也就是只含数字4, 7且4, 7的数量相等的数)加起来也不过几万个,可以采用打表的方法来把所有的super lucky number存储起来.因为4,7数量须相等,所以可以用一个二进制数的0,1来代替,先限定4,7数量分别为 i,之后就是求出包含 i 个0和 i 个1的 2*i 位所有这样的二进制数,然后简单转换一下(1->7, 0->4,这样子能从小到大

hdu5676 ztr loves lucky numbers DFS

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5676 题意: 定义幸运数为:只存在4和7且4和7数量相等的数,给出n,求比>=n的最小幸运数 思路: 因为n最多18位,幸运数最大是10个4,10个7,这种情况特判掉,爆longlong,其他的暴力搜出所有长度从2-18的幸运数,因为最多9个4,9个7,然后二分找出比这个数大的那个数 代码: 1 #include <bits/stdc++.h> 2 using namespace std;

hdoj ztr loves lucky numbers 5676 (dfs模拟)

ztr loves lucky numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 918    Accepted Submission(s): 389 Problem Description ztr loves lucky numbers. Everybody knows that positive integers ar

hdu-5676 ztr loves lucky numbers(乱搞题)

题目链接: ztr loves lucky numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 ztr喜欢幸运数字,他对于幸运数字有两个要求 1:十进制表示法下只包含4.7 2:十进制表示法下4和7的数量相等 比如47,474477就是 而4,744,467则不是 现在ztr想知道最小的但不小于n的幸运数字是多少 输入描述 有TT(1≤T≤10?5??)组数据,

[HDOJ5676]ztr loves lucky numbers(状压枚举,打表,二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5676 题意:输入一个正整数n(n <=10^18),求不小于n的只有4和7组成的数,且4和7数量相同 枚举2~18位偶数位的4.7的组合,01分别代表4或7.存下来后排序,二分查询. trick就是LL存不下20位的数,但是n<=10^18,那么只要特判大于777777777444444444的数都输出44444444447777777777就行了. 1 #include <bits/std

ztr loves lucky numbers(STL)

ztr喜欢幸运数字,他对于幸运数字有两个要求 1:十进制表示法下只包含4.7 2:十进制表示法下4和7的数量相等 比如47,474477就是 而4,744,467则不是 现在ztr想知道最小的但不小于n的幸运数字是多少 输入描述 有T(1≤n≤105)组数据,每组数据一个正整数n(1≤n≤1018) 输出描述 有T行,每行即答案 输入样例 2 4500 47 输出样例 4747 47 Hint 请尽可能地优化算法,考虑全面 LuckNum.h #include <iostream> class

hdu 5677 ztr loves substring 二维费用背包+回文

题目链接: hdu 5677 ztr loves substring 官方题解: //这部分是错的(首先,对于每一个串i跑一次manancher,令g[i][j]=p[j]-1g[i][j]=p[j]−1 这样,g就存储了所有的回文子串的长度 为了方便,把g降到一维表示) 首先,因为字符串长度较小,所以直接二重for循环找就好了,用一个数组 g记录各个回文串的长度 不妨把每一个子串抽象成一个物品 费用为二维的,即{长度,1} 价值是Bool型的 这样就成了一个二维判断可行性费用背包问题 设f(i

HDU 5675 ztr loves math

ztr loves math Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 896    Accepted Submission(s): 347 Problem Description ztr loves research Math.One day,He thought about the "Lower Edition" of