ABC363 D - Palindromic Number

由于赛时不会写,补题时也花了较大功夫才弄懂,特写一篇题解来加深理解

Problem Statement

A non-negative integer X X X is called a palindrome number if its decimal representation (without leading zeros) is a palindrome.
For example, 363 363 363, 12344321 12344321 12344321, and 0 0 0 are all palindrome numbers.

Find the N N N-th smallest palindrome number.

题意

你需要输出第N大的回文数。

分析

我们先写出几项找找规律,设回文数长度为 d d d
d = 1 d = 1 d=1,9 ( 1 − − − 9 ) (1 --- 9) (19)
d = 2 d = 2 d=2,9 ( 11 − − − 99 ) (11 --- 99) (1199)
d = 3 d = 3 d=3,90 ( 11 − − − 99 ) (11 --- 99) (1199)
d = 4 d = 4 d=4,90
d = 5 d = 5 d=5,900
我们发现长度为d的回文数,只有 9 × 1 0 ( d + 1 ) / 2 − 1 9 \times 10^{(d + 1)/2 - 1} 9×10(d+1)/21个。有了这个重要结论,我们就可以缩小问题了。现在需要求第 N N N大的数,我们枚举第N大的数的长度 l e n len len,当 N N N > 9 × 1 0 ( l e n + 1 ) / 2 − 1 9 \times 10^{(len + 1)/2 - 1} 9×10(len+1)/21,说明 N N N的长度大于 l e n len len,我们将 N − 9 × 1 0 ( l e n + 1 ) / 2 − 1 N - 9 \times 10^{(len + 1)/2 - 1} N9×10(len+1)/21,这样就缩小了问题。当 N N N < 9 × 1 0 ( l e n + 1 ) / 2 − 1 9 \times 10^{(len + 1)/2 - 1} 9×10(len+1)/21时,我们知道 l e n len len长度的最小回文数总是 1000001 1000001 1000001这样的形式的,由于是回文的我们只看前半数位,假设当前求第 N N N大的数,我们拿出前半数位,前半数位的数加上 N N N就是这个所求回文数的前半数位了,将前半数位翻转加上去就是答案了。由于数可能会超过LL,我们使用字符串模拟的做法。注意最后求答案时,对于奇数长度的数,我们拼接前后半段时,需要将前半段的末尾去掉,保证是一个奇数长度的数。

#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
const int N = 1e5+5;
LL n;
long long TEN(int x) {   // 求10的x次的递归函数,使用pow也可
    return x == 0 ? 1 : TEN(x - 1) * 10;
}

void solve(){
    cin >> n;
    if(n == 1) {
        cout << 0 << endl;
        return ;
    }
    n--;
    for(int p = 1;  ; p++){
        LL d = (p + 1)/2;
        LL k = TEN(d - 1);
        if(n > k * 9){
            n -= k * 9;
        }else{
            string s = to_string(TEN(d - 1) + n - 1); //数字变字符串操作
            string t = s;
            reverse(t.begin(), t.end());
            if(p % 2 == 1) s.pop_back(); // 特判奇数长度
            s = s + t;
            cout << s << endl;
            return ;
        }
    }

}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值