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

时间:2022-08-20 20:54:44
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(≤n≤) cases

For each cases:

The only line contains a positive integer n(≤n≤). This number doesn't have leading zeroes.
Output
For each cases
Output the answer
Sample Input

Sample Output

直接暴力显然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数量相等的数
 void dfs(ll sum,int c1,int c2){
if(c1>=k1 && c2>=k2){
ans[num++]=sum;
return;
}
if(c1<k1) dfs(sum*+,c1+,c2);
if(c2<k2) dfs(sum*+,c1,c2+);
}

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

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

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

AC代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define N 1000000
int k1,k2;
ll ans[N];
int num;
ll n;
void dfs(ll sum,int c1,int c2){
if(c1>=k1 && c2>=k2){
ans[num++]=sum;
return;
}
if(c1<k1) dfs(sum*+,c1+,c2);
if(c2<k2) dfs(sum*+,c1,c2+);
}
void init(){
num=;
for(int i=;i<=;i+=){
k1=k2=i/;
dfs(,,);
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--){
scanf("%I64d",&n);
int cnt = lower_bound(ans,ans+num,n)-ans;
if(cnt<num){
printf("%I64d\n",ans[cnt]);
}else{
printf("44444444447777777777\n");
}
}
return ;
}