(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代码:

 1 #include<iostream>
 2 #include<stack>
 3 #include<cmath>
 4 #include<stdio.h>
 5 #include<algorithm>
 6 #include<string>
 7 #include<cstring>
 8 using namespace std;
 9 # define ll long long
10 const int maxn = 1e5+100;
11 ll base=1;
12 ll cal(ll t)
13 {
14     ll ans=0;
15     ll tmp=t;
16     while(tmp)
17     {
18         base*=10;
19         tmp/=10;
20     }
21     base/=10;
22     ll base1=base;
23     while(t)
24     {
25         ans+=(t-base1+1);
26         t/=10;
27         base1/=10;
28     }
29     return ans;
30 }
31 int main()
32 {
33     ll k,m;
34     scanf("%lld %lld",&k,&m);
35     ll tmp=cal(k);
36     m-=tmp;
37     if(m<0)
38         printf("0
");
39     else if(m==0)//  当正好凑够的时候
40         printf("%lld
",k);
41     else if(base==k)//当无论怎么添加都填不上的时候。注意这个条件和上面的条件的判断顺序,
42         printf("0
");
43     else
44     {
45         ll t=k-base;
46         t*=10;
47         base*=10;
48         while(m>t)
49         {
50             m-=t;
51             base*=10;
52             t*=10;
53         }
54         printf("%lld
",base+m-1);
55     }
56     return 0;
57 }
原文地址:https://www.cnblogs.com/letlifestop/p/10294237.html