洛谷 P2022 有趣的数 题解

一、题目:

洛谷原题

二、思路:

实在想不出来啊!!!又无耻看题解。完了,今年提高组要凉。

数学推导。

首先考虑K所有可能的位置中,最小的那一个。

以K=234为例,计算K之前(包括K)有几个元素:

一位数:1~2(2个)

两位数:10~23(14个)

三位数:100~234(135个)

所以K=234时,最小可能的位置是2+14+135=151。

记K最小可能的位置是pos,那么显然有:

如果pos==m,答案就是K。

如果pos>m,无解。

如果pos<m,我们要在K之前加入m-pos个元素。

挨个位数加呗。

两位数不够加三位数,三位数不够加四位数,四位数不够加五位数……

如果够了,跳出循环即可。

具体实现看代码。

三、代码:

#include<iostream>
#include<cstdio>
#include<cstring>

#define LL long long

using namespace std;
template<class Type>
inline Type read(void){
    Type x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

int K,m;
int base,len;
LL mi[20];//mi[i]为10的i次幂。
LL ans;

inline int calc(int k){
    char s[12]={0};
    sprintf(s,"%d",k);
    int ans=0,w=0;
    len=strlen(s);
    for(register int i=0;i<len;++i){
        w=w*10+s[i]-'0';
        ans+=w-mi[i]+1;
    }
    return ans;
}

int main(){
    mi[0]=1;
    for(register int i=1;i<19;++i)mi[i]=mi[i-1]*10;
    K=read<int>();
    m=read<int>();
    for(register int i=0;i<10;++i){
        if(K==mi[i]&&m!=i+1){
            cout<<0<<endl;return 0;
        }
    }
    base=calc(K);//计算pos。
    if(m<base){cout<<0<<endl;return 0;}
    if(m==base){cout<<K<<endl;return 0;}
    ans=mi[len];
    m-=base;
    for(register int i=1;;++i){//挨个位数加。
        LL tmp=K*mi[i]-mi[len+i-1];
        if(m>tmp){m-=tmp;ans*=10;}
        else break;
    }
    ans+=m-1;//注意细节。
    cout<<ans<<endl;//李煜东:卡什么常啊,能不能有点追求。我:要有追求!
    return 0;
}

转载于:https://www.cnblogs.com/little-aztl/p/9788434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值