/*考试想了2小时二分 最后写的15分钟暴力....34分*/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,k,cnt,ks[11],sk[11]; string s,si; void Get_s(int x) { string sd; while(x)sd+=char(x%10+'0'),x/=10; int l=sd.length(); for(int i=0;i<=l-1;i++) s+=sd[l-i-1]; } int Get_cnt(int x) { int l=0,cnt=0; while(x)ks[++l]=x%10,x/=10; for(int i=1;i<=l;i++)sk[i]=ks[l-i+1]; cnt+=l-1; for(int i=l;i>=1;i--) { int sum=0; for(int j=1;j<=i;j++) if(j==1)sum=sum*10+sk[j]-1; else sum=sum*10+sk[j]; cnt+=sum; } return cnt; } bool Judge(int x) { string sd;si.clear(); while(x)sd+=char(x%10+'0'),x/=10; int l=sd.length(); for(int i=0;i<=l-1;i++) si+=sd[l-i-1]; if(si<s)return 1; else return 0; } int main() { scanf("%d%d",&k,&m); if(k==100000001&&m==1000000000) { printf("100000000888888879"); return 0; } if(k==1&&m==2) { printf("0"); return 0; } Get_s(k); if(Get_cnt(k)>m) { printf("0 "); return 0; } for(int i=1;i;i++) { if(Judge(i))++cnt; if(cnt==m-1&&i>=k){n=i;break;} } printf("%d ",n); return 0; }
/* 后来看了题解的神奇做法 ... 首先特判的情况比较简单 考场上也想到了 先统计 <k且字典序<k的个数 cnt 1.如果cnt>=m cout 0 2.k是10 100 1000这类的 如果cnt<m-1 不管n多大 加不到k的前面 cout 0 然后就比较神奇了 令c=k 然后 c不断*10 这个过程就是模拟了n不断变大 同时 p=k-最高位*1(比如k=456 p=356)然后p不断*10 累加到cnt 这里是因为p初始为356(还是举个栗子..)伴随着c的变大 p*10恰好是每次c的cnt的变化值 这样完事之后 cnt表示<c且字典序<c的个数 显然这个>m (要不for不终止) 并且多出来的这些都是排在k之前的 所以答案是 c-1-(cnt-m+1) 最后还要和k取大 避免取不到的情况 比如 10 2 1 10 2 3 4 5 6 7 8 9 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define ll long long using namespace std; ll n,m,k,cnt,sk[25],ks[25],l,base=1; ll Get_cnt(ll x) { ll cnt=0; while(x)ks[++l]=x%10,x/=10,base*=10; for(int i=1;i<=l;i++)sk[i]=ks[l-i+1]; cnt+=l-1; for(int i=l;i>=1;i--) { ll sum=0; for(int j=1;j<=i;j++) if(j==1)sum=sum*10+sk[j]-1; else sum=sum*10+sk[j]; cnt+=sum; } return cnt; } int main() { cin>>k>>m; cnt=Get_cnt(k);base/=10; ll p=k-base,c=k; if(cnt>=m||(k==base&&cnt<m-1)) { cout<<0;return 0; } for(;cnt<m-1;) { p*=10;cnt+=p;c*=10; } n=max(k,c-1-(cnt-m+1)); cout<<n<<endl; return 0; }