zoukankan      html  css  js  c++  java
  • 今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?

    #  由于n和m都是10^18的范围,暴力明显不行,只能dfs了。
    # 先预处理n的十进制,存到num数组中,长度计算出来为len, 答案存到Num中。
    # 写个函数cntOfBeginNum(int *Num,int anslen),计算以num为前缀的小于等于n的数的个数cnt,考虑长度比n的十进制长度小的数,则cnt+=1+10+100+1000......
    # 长度和n相等的则要特判一下,前缀Num和num的前缀有3种关系,> = < ,先判断是哪种,再计算。
    # 然后考虑答案的最高位非0,我们从1到9枚举,如果cnt=cntOfBeginNum(Num,1)>=m,则dfs()下去。否则,m-=cnt;
    # 然后dfs函数里面,如果m==1,那么直接输出当前值就是答案了。。 比如当前值是23,如果m是1,答案是23(以一个数为前缀的字典序最小的就是它本身)。 否则再枚举第3高位,从
    # 0~9枚举进行dfs....
    # 其实也可以不dfs,压根没有回溯。 直接走一步算一步就是了。
    #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> using namespace std; const int maxn=20; int len; int num[maxn],ans[maxn]; long long n,m; void printans(int *ans,int cnt){ for(int i=1;i<=cnt;i++)cout<<ans[i]; puts(""); } void init(){ len=0; while(n){ num[++len]=n%10; //cout<<len<<" "<<num[len]<<endl; n/=10; } //cout<<"len:"<<len<<endl; } long long valuebeginIndex(int beg){ long long cnt=0; for(int i=beg;i<=len;i++){ cnt=cnt*10+num[len-i+1]; } return cnt; } long long cntOfBeginNum(int *Num,int anslen){ long long k=1; long long cnt=0; for(int i=0;i+anslen<len;i++){ cnt+=k; k*=10; } int op=0; for(int i=1;i<=anslen;i++){ int id=len-i+1; if(num[id]>Num[i]){ op=-1; break; } else if(num[id]<Num[i]){ op=1; break; } } //cout<<" op:"<<op<<endl; if(op==0){ if(anslen==len)return 1; return valuebeginIndex(anslen+1)+1+cnt; } else if(op==1){ return cnt; } else { long long k=1; for(int i=0;i<len-anslen;i++)k*=10; return cnt+k; } } void dfs(int *ans,int cur,long long m){ //printans(ans,cur); if(m==1){ printans(ans,cur); return; } m--; for(int i=0;i<=9;i++){ ans[cur+1]=i; long long cnt=cntOfBeginNum(ans,cur+1); //cout<<i<<" "<<m<<" " <<cnt<<endl; if(cnt>=m){ dfs(ans,cur+1,m); return; } else m-=cnt; } } void run(){ init(); for(int i=1;i<=9;i++){ ans[1]=i; long long cnt=cntOfBeginNum(ans,1); //cout<<i<<" "<<cnt<<" "<<m<<endl; if(cnt>=m){ dfs(ans,1,m); break; } else m-=cnt; } } int main(){ //freopen("in","r",stdin); while(cin>>n>>m)run(); return 0; }
  • 相关阅读:
    【BZOJ3784】树上的路径 点分治序+ST表
    【BZOJ3698】XWW的难题 有上下界的最大流
    【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
    【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
    【BZOJ2724】[Violet 6]蒲公英 分块+二分
    【BZOJ3697】采药人的路径 点分治
    【BZOJ4026】dC Loves Number Theory 分解质因数+主席树
    【BZOJ3510】首都 LCT维护子树信息+启发式合并
    Python Web学习笔记之socket编程
    Python Web学习笔记之socket套接字
  • 原文地址:https://www.cnblogs.com/wshh/p/5921984.html
Copyright © 2011-2022 走看看