洛谷 2022 有趣的数

/*考试想了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;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5737518.html