(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\n"); 39 else if(m==0)// 当正好凑够的时候 40 printf("%lld\n",k); 41 else if(base==k)//当无论怎么添加都填不上的时候。注意这个条件和上面的条件的判断顺序, 42 printf("0\n"); 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\n",base+m-1); 55 } 56 return 0; 57 }