【競プロ典型90問】「082 - Counting Numbers(★3)」解法
Free-PhotosによるPixabayからの画像

このシリーズではE869120さんによって作成された競プロ典型90問をPythonで解いています。

問題

082 - Counting Numbers(★3)

ポイント

1度、各桁ごとに書かれる文字の個数を整理してみましょう。
例えば、1桁の数字は1~9まであり黒板に書かれる文字の総数は下記の式で求めることができます。

2桁(10 ~ 99)については

3桁(100 ~ 999)については

となります。

ここで、書かれる数字の総数(図の水色)の計算に利用しているのが等差数列の公式になります。
ここでは詳しく説明しませんが、もし忘れてしまった方は下記ページから確認してみてください。
1からnまでの和を求める公式 - 具体例で学ぶ数学

この問題では、LからRまでの各桁ごとに書かれる文字を計算→合算することで解答を得ることができます。

以上を踏まえ、実装したコードがこちらです。

コード

def main():
    import sys
    sys.setrecursionlimit(10 ** 9)
    input = sys.stdin.readline

    L, R = map(int, input().split(" "))

    mod = 10 ** 9 + 7
    min_digit = len(str(L))  # xの範囲で最も小さい桁数
    max_digit = len(str(R))  # xの範囲で最も大きい桁数

    ans = 0
    # 各桁ごとに書かれる文字数を求める
    for i in range(min_digit, max_digit + 1):
        min_num = max(L, 10 ** (i - 1))  # 同じ桁の中での最小値(等差数列の初項)。基本は10 ** (i - 1)だがLが含まれる桁ではLが最小値
        max_num = min(R, 10 ** i - 1)  # 同じ桁の中での最大値(等差数列の末項)。基本は10 ** i - 1だがRが含まれる桁ではRが最大値
        num = max_num - min_num + 1  # 数列の項数

        ans += num * (min_num + max_num) // 2 * i

    print(ans % mod)


if __name__ == '__main__':
    main()

おすすめの記事