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
请尽可能地优化算法,考虑全面
这个题一路if、else也是一个很好的选择方式,不过手残脑残党,我还是建议和我一样来dfs0.0
思路:
首先最好想的就是输入不用long long,改为char输入,因为我们每一个数字都有可能分析到,所以我们可以使用字符输入。
我们把字符串分成两种情况,一种是奇数长度的,一种是偶数长度的,首先我们处理奇数长度的:
奇数长度的我们无论它里边的内容是什么,只要是比它长的结果都是可行结果,那么最小解呢?当然不难想到,假如输入是555(三个长度的时候),我们无脑输出4477(输出四个长度里边最小的)就好,假如输入是55555(五个长度的时候)我们无脑输出444777(输出留个长度里边最小的)就好。
辣么如果字符串长度是偶数的时候呢?
如果这个时候一路if、else的话,很容易就会WA啊WA啊,WA,所以呢,我这种手残脑残党,就选择dfs咯~反正2^18也不大,也才26万+操作,如果加上点剪枝,按理是不会超时滴。所以我就dfs咯~找到一个比当前串大的串(长度相等的时候的),(strcmp判断即可),蓝后输出就好啦~
辣么如果当前长度相等的偶数串得不到结果怎么办嘞~?那么就无脑输出444.....777.....咯,假如输入的是9999,明显当前长度的47串没有符合的条件,辣么就输出444777(当前长度加2的长度最小的数)就好咯~
思路整个建立完成,剩下的就是代码实现咯~:不过说句实话,真心跑了很久喵0.0
#include<stdio.h> #include<string.h> using namespace std; char a[25]; char output[25]; int ok; void dfs(char s[],int cont,int mubiao,int cont4,int cont7) { if(cont4>mubiao/2)return ; if(cont7>mubiao/2)return ; if(ok==1)return ; if(cont==mubiao) { if(cont4==cont7) { if(strcmp(s,a)>=0) { printf("%s\n",s); ok=1; } } return ; } for(int i=0; i<2; i++) { if(i==0) { s[cont]='4'; s[cont+1]='\0'; dfs(s,cont+1,mubiao,cont4+1,cont7); if(ok==1)return ; } if(i==1) { s[cont]='7'; s[cont+1]='\0'; dfs(s,cont+1,mubiao,cont4,cont7+1); if(ok==1)return ; } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%s",a); int n=strlen(a); int flag=0; ok=0; for(int i=0; i<n; i++) { if(a[i]=='4'||a[i]=='7')continue; } if(n%2==1)//如果是奇数情况 { for(int i=0; i<=n/2; i++) { printf("4"); } for(int i=n/2+1; i<=n; i++) { printf("7"); } printf("\n"); } if(n%2==0)//如果是偶数情况 { char s[25]; dfs(s,0,n,0,0); if(ok==1)continue; else { for(int i=0; i<(n+2)/2; i++) { printf("4"); } for(int i=(n+2)/2; i<=n+1; i++) { printf("7"); } printf("\n"); } } } }