题目:
题意:
将
1
—
n
1—n
1—n的所有正整数都按照字典序排序,指定
k
、
m
k、m
k、m
问
n
n
n至少是多少时
k
k
k的位置是第
m
m
m位
分析:
这么大的数据范围我们显然不能一个个枚举,我直接推规律好了
有个十分明显的规律,
1
、
10
、
100
1、10、100
1、10、100这些数肯定在前面的
当
n
n
n小于
k
k
k时,能对答案做出贡献的必定是前几位小于
k
k
k
例子:
k
=
234
k=234
k=234
那么一位数能做出贡献的就是
1
—
2
1—2
1—2
两位数能做出贡献的就是
10
—
23
10—23
10—23
三位数能做出贡献的就是
100
—
233
100—233
100—233
我们计算出总贡献后得到
s
s
s
若
s
=
m
s=m
s=m那
n
=
k
n=k
n=k,
s
>
m
s>m
s>m则肯定不合法
现在我们开始考虑
s
s
s不足的情况,我们直接从
1
、
10
、
100
…
…
1、10、100……
1、10、100……开始计算
最后答案统计时,我们需要
−
1
-1
−1,因为当前的
100
…
…
100……
100……已经计算过了
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL mm[25],len;
LL solve(int x)
{
char s[25];
sprintf(s,"%d",x);
LL ans=0,num=0;len=strlen(s);
for(LL i=0;i<len;i++)
{
num=num*10+s[i]-'0';
ans+=num-mm[i]+1;
}
return ans;
}
int main()
{
int k=read(),m=read();
mm[0]=1;
for(LL i=1;i<19;i++) mm[i]=mm[i-1]*10;
for(LL i=0;i<10;i++) if(mm[i]==k&&m!=i+1) return !printf("0");
LL bace=solve(k);
if(bace>m) return !printf("0");
if(bace==m) return !printf("%d",k);
LL ans=mm[len];
m-=bace;
LL i=1;
while(1)
{
LL sum=k*mm[i]-mm[len+i-1];
if(sum>=m) break;
else m-=sum,ans*=10;
i++;
}
cout<<ans+m-1;
return 0;
}