072 1到n中1的出现次数
Table of Contents

ac

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;

public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws Exception {
        String line = reader.readLine();
        long n = Long.valueOf(line);
        /*
这里的 X∈[1,9],因为 X=0 不符合下列规律,需要单独计算。

首先要知道以下的规律:

从 1 至 10,在它们的个位数中,任意的 X 都出现了 1 次。
从 1 至 100,在它们的十位数中,任意的 X 都出现了 10 次。
从 1 至 1000,在它们的百位数中,任意的 X 都出现了 100 次。
依此类推,从 1 至 10i,在它们的左数第二位(右数第 i 位)中,任意的 X 都出现了 10i−1 次。

接下来以 n=2593,X=5 为例来解释如何得到数学公式。从 1 至 2593 中,数字 5 总计出现了 813 次,
* 其中有 259 次出现在个位,260 次出现在十位,294 次出现在百位,0 次出现在千位。

现在依次分析这些数据,首先是个位。从 1 至 2590 中,包含了 259 个 10,因此任意的 X 都出现了 259 次。
* 最后剩余的三个数 2591, 2592 和 2593,因为它们最大的个位数字 3 < X,因此不会包含任何 5。

然后是十位。从 1 至 2500 中,包含了 25 个 100,因此任意的 X 都出现了 25×10=250 次。
* 剩下的数字是从 2501 至 2593,它们最大的十位数字 9 > X,因此会包含全部 10 个 5。最后总计 250 + 10 = 260。

接下来是百位。从 1 至 2000 中,包含了 2 个 1000,因此任意的 X 都出现了 2×100=200 次。
* 剩下的数字是从 2001 至 2593,它们最大的百位数字 5 == X,
* 这时情况就略微复杂,它们的百位肯定是包含 5 的,但不会包含全部 100 个。
* 如果把百位是 5 的数字列出来,是从 2500 至 2593,数字的个数与百位和十位数字相关,是 93+1 = 94。

最后总计 200 + 94 = 294。
         */
        long x = 1;
        long ans = 0;
        long m = n;
        long base = 1;
        while (m > 0){
            long curVal = m % 10; // 计算的当前位置的值,当前所处位置(个,十,百,千)
            long left = m / 10; // curVal 左边的值
            long right = n % base; // curVal 右边的值
            if(curVal < x){
                ans += left * base;
            }else if(curVal == x){
                // 要加上右边的数字 例如 2153,计算到百位的时候
                // 100 101 ... 153 53个数都能使得百位是1,需要加上
                ans += left * base + (right+1);
            }else {
                // 要加上base 例如 2253,计算到百位的时候
                // 100 101 ... 153 ... 199 个数都能使得百位是1,是完整的100个数
                ans += left * base + base;
            }
            base *= 10;
            m /= 10;
            // System.out.println(ans);
        }

        System.out.println(ans);
    }

}
/*
11

4

2345

1775
 */