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∗2log10n)
考虑到T特别大,不可能每次都DFS
而经过计算,2^{18}=262144218=262144,所以全部储存下来
对于每次询问,二分即可
考虑一个边界条件,即当结果爆ll怎么办?
即答案应当为10个4、10个7的时候,显然unsigned long long也不行
那么只能采用特判了
首先,由于每一位只能是4或7,且
2^{18}=262144218=262144,故而考虑离线打表,即利用dfs求解出所有只含数字4和7,且4和7数量相等的数
2^{18}=262144218=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 ",ans[cnt]); 36 }else{ 37 printf("44444444447777777777 "); 38 } 39 } 40 return 0; 41 }