Skip to content

14054: 【原4054】伪回文数

题目

题目描述

author: Will 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4054

Description

口口君特别喜欢回文数,由于已经考过回文数,口口君只好造出了伪回文数。定义如下:
对于一个十进制非负整数 X,如果他的第一位等于他的最后一位,则称 X 为伪回文数。
如,101, 477474 以及 9 都属于伪回文数。口口君很好奇对于一个给定区间 [L, R] ( L <= R 且 L, R 都是非负整数)究竟有多少个这样的伪回文数。

Input Format

一行,包含非负整数 L 和 R (1 <= L <= R <= 10^18)。

Output Format

一行,区间 [L, R] 内伪回文数的个数。

Sample Input

2 47

Sample Output

12

Sample Input

47 1024

Sample Output

98

数据范围

对于 50% 的数据 (0 <= R - L <= 10^5)  
对于 100% 的数据 (1 <= L <= R <= 10^18)

BugenZhao's solution

//
// Created by BugenZhao on 2019/3/23.
//

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

using namespace std;

using ll=long long;

ll tmpe[20] = {0, 1};
ll *e = tmpe + 1;

int getLength(ll num) {
    int ans = 1;
    while (num /= 10) {
        ++ans;
    }
    return ans;
}

int getFront(ll num) {
    while (true) {
        if (num <= 9) break;
        num /= 10;
    }
    return (int) num;
}

int main() {
    for (int i = 1; i < 19; ++i) {
        e[i] = e[i - 1] * 10;
    }
    ll l, r;
    cin >> l >> r;
    ll ans = 0;

    int lLength = getLength(l), rLength = getLength(r);
    int lFront = getFront(l), rFront = getFront(r);

    if (lLength == rLength) {
        ll N = e[lLength - 1] * lFront + 9 * e[lLength - 2] + lFront;
        ll n = e[lLength - 1] * rFront + rFront;
        if (lFront == rFront) {
            if (l <= n) {
                if (r < n) ans += 0;
                else ans += (r - n) / 10 + 1;
            } else {
                if (r < n) ans += (r - l) / 10;
                else ans += (n - l) / 10;
            }
        } else {
            ans += (N - l > 0) ? (N - l) / 10 : 0;
            ans += (l - n > 0) ? (l - n) / 10 : 0;
            ans += (rFront - lFront - 1) * (lLength == 1 ? 1 : e[lLength - 2]);
        }
        cout << ans << endl;
        return 0;
    }
    for (int i = lLength + 1; i < rLength; ++i) {
        ans += 9 * e[i - 2];
    }


    for (int i = lFront; i < 10; ++i) {
        if (i != lFront) {
            ans += e[lLength - 2];
            continue;
        }
        ll N = e[lLength - 1] * i + 9 * e[lLength - 2] + i;
        ll tmp = N - l;
        ans += (tmp > 0) ? tmp / 10 : 0;
    }

    for (int i = 1; i <= rFront; ++i) {
        if (i != rFront) {
            ans += e[lLength - 2];
            continue;
        }
        ll n = e[lLength - 1] * i + i;
        ll tmp = l - n;
        ans += (tmp > 0) ? tmp / 10 : 0;
    }

    cout << ans << endl;
    return 0;
}

FineArtz's solution

/* 伪回文数 */
#include <iostream>
#include <cmath>
using namespace std;

inline int firstDigit(long long r){
    while (r >= 10) r /= 10;
    return r;
}

long long f(long long x){
    if (x < 10) return x + 1;
    return (9 + x / 10 + (int)(x % 10 >= firstDigit(x)));
}

int main(){
    long long l, r;
    cin >> l >> r;
    long long ans = f(r) - f(l - 1);
    cout << ans << endl;
    return 0;
}

ligongzzz's solution

#include "iostream"
#include "cstdio"
#include "cstring"
#include "cmath"
using namespace std;

long long poww(int i) {
    long long ans = 1;
    for (int j = 0; j < i; ++j)
        ans *= 10;
    return ans;
}

long long cal(char* ch) {
    int len = strlen(ch);
    if (len == 1)
        return ch[0] - '0';
    if (len == 2) {
        if (ch[0] > ch[1])
            return ch[0] - '1' + 9;
        else
            return ch[0] - '0' + 9;
    }
    int temp = ch[0] > ch[len - 1] ? ch[len - 1] - '0' : ch[0] - '0';

    long long ans = 9;
    for (int i = 0; i < len - 2; ++i)
        ans += (long long)9 * poww(i);
    long long p = 1;
    char ch1[100];
    strcpy(ch1, ch + 1);
    ch1[strlen(ch1) - 1] = 0;
    sscanf(ch1, "%lld", &p);
    if (ch[0] <= ch[len - 1])
        ans += p + 1;
    else
        ans += p;
    ans += (long long)(ch[0] - '1') * poww(len - 2);
    return ans;
}

int main() {

    char L[100], R[100];
    cin >> L >> R;

    long long Lans, Rans;
    Lans = cal(L);
    Rans = cal(R);

    if (L[0] == L[strlen(L) - 1])
        ++Rans;

    cout << Rans - Lans;

    return 0;
}

skyzh's solution

#include <iostream>
using namespace std;

long long get_sum(long long R) {
    long long F = 1, D = 1, K = 0;
    long long SUM = 0;
    for (int i = 1; i <= 19; i++) {
        for (int j = 1; j <= 9; j++) {
            long long LOWER_BOUND = j * D;
            long long UPPER_BOUND = j * D + K * 10;
            if (R < LOWER_BOUND) return SUM;
            if (R < UPPER_BOUND) {
                long long T = R / 10, B = 1;
                while (T > 0) { T /= 10; B *= 10; }
                SUM += (R - B * j) / 10;
                if (R % 10 >= j) ++SUM;
            } else SUM += K + 1;
        }
        F *= 10;
        D = F + 1;
        if (i >= 2) K = K * 10 + 9;
    }
    return SUM;
}
int main() {
    long long L, R;
    cin >> L >> R;
    cout << get_sum(R) - get_sum(L - 1) << endl;
    return 0;
}