2 4500 47
4747 47
/************************************************************************/
附上该题对应的中文题
ztr喜欢幸运数字,他对于幸运数字有两个要求 1:十进制表示法下只包含4、7 2:十进制表示法下4和7的数量相等 比如47,474477就是 而4,744,467则不是 现在ztr想知道最小的但不小于n的幸运数字是多少
有T(1≤T≤105)组数据,每组数据一个正整数n,1≤n≤1018
有T行,每行即答案
2 4500 47
4747 47
请尽可能地优化算法,考虑全面
出题人的解题思路:
直接暴力显然TLE,考虑按位DFS
每一位只可能是4或7
所以根据这个来DFS即可,时间复杂度O(T∗2log10n)
考虑到T特别大,不可能每次都DFS
而经过计算,218=262144,所以全部储存下来
对于每次询问,二分即可
考虑一个边界条件,即当结果爆ll怎么办?
即答案应当为10个4、10个7的时候,显然unsigned long long也不行
那么只能采用特判了
int k1,k2,p; __int64 ans[N]; void dfs(__int64 sum,int c1,int c2) { if(c1>=k1&&c2>=k2) { ans[p++]=sum; return ; } if(c1<k1)//4 dfs(sum*10+4,c1+1,c2); if(c2<k2)//7 dfs(sum*10+7,c1,c2+1); }结果存储在ans数组中,此时可以得到符合条件的数有66196+1个,而数据有T组,好吧,那就二分查找
q=lower_bound(ans,ans+p,n)-ans;需要注意的一点是,当n>777777777444444444的时候,18位数里面已经没有比这更大的符合条件的数了,那么只能特判一下,解为最小的20位符合条件的数,即44444444447777777777
/*Sherlock and Watson and Adler*/ #pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<complex> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 100005; const int M = 40; const int inf = 100000000; const int mod = 2009; int k1,k2,p; __int64 ans[N]; void dfs(__int64 sum,int c1,int c2) { if(c1>=k1&&c2>=k2) { ans[p++]=sum; return ; } if(c1<k1)//4 dfs(sum*10+4,c1+1,c2); if(c2<k2)//7 dfs(sum*10+7,c1,c2+1); } int main() { int i,t,q; __int64 n; p=0; for(i=2;i<=18;i+=2) { k1=k2=i/2; dfs(0,0,0); } //printf("p=%d\n",p); /*for(i=0;i<p;i++) printf("%I64d ",ans[i]);*/ scanf("%d",&t); while(t--) { scanf("%I64d",&n); q=lower_bound(ans,ans+p,n)-ans; //printf("q=%d\n",q); if(q<p) printf("%I64d\n",ans[q]); else puts("44444444447777777777"); } return 0; }菜鸟成长记