(P2022 有趣的数)||(zoj Little Sub and Mr.Potato's Math Problem)(思维)

时间:2023-03-09 05:01:16
(P2022 有趣的数)||(zoj  Little Sub and Mr.Potato's Math Problem)(思维)

题目链接:https://www.luogu.org/problemnew/show/P2022

题目大意:中文题目

具体思路:

第一步:我们可以先计算出当前的数前面按照字典序的话,前面有多少数(包括自己)。

(具体计算过程,456.首先是三位数的数在456前面的个数,就是(100->456),然后再就是两位数(10-45),然后再就是一位数1-4,严格遵守字典序)。

第二步:如果说当前的数前面的数的个数大于m的话,这个时候肯定是不符合情况的,如果说刚好凑起来的话,这个时候输出k就可以了。

第三步:经过了第二步,发现当前的数N取k的时候凑不起来,我们就需要通过增加n来使得k的位数往后移动。举个例子,456不够,我们就可以通过添加1000-4560之间的数来使得456的位数往后移动,如果还不够我们就添加10000-45600之间的数使得456的位数往后移动。

第四步:我们需要判断一种特殊情况,比如说 10 10这个样例,10前面的数只有1,但是你如果加100之后的,也不会使得10的位数往后移动,这个时候就应该输出0。

(看了个题解,研究了三四个小时。。。。。。)

AC代码:

 #include<iostream>
#include<stack>
#include<cmath>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
# define ll long long
const int maxn = 1e5+;
ll base=;
ll cal(ll t)
{
ll ans=;
ll tmp=t;
while(tmp)
{
base*=;
tmp/=;
}
base/=;
ll base1=base;
while(t)
{
ans+=(t-base1+);
t/=;
base1/=;
}
return ans;
}
int main()
{
ll k,m;
scanf("%lld %lld",&k,&m);
ll tmp=cal(k);
m-=tmp;
if(m<)
printf("0\n");
else if(m==)// 当正好凑够的时候
printf("%lld\n",k);
else if(base==k)//当无论怎么添加都填不上的时候。注意这个条件和上面的条件的判断顺序,
printf("0\n");
else
{
ll t=k-base;
t*=;
base*=;
while(m>t)
{
m-=t;
base*=;
t*=;
}
printf("%lld\n",base+m-);
}
return ;
}