2 1 10 1 20
Case #1: 0 Case #2: 1HintThe answer maybe very large, we recommend you to use long long instead of int.
开始可以暴力打印一些出来看看,注意0能够被10整除
0 - 100 10
0 - 1000 100
0 - 99 10
0 - 91 10
0 - 90 9
可以发现有近似num / 10的规律,仔细观察后发现其实确实粗略来看是每10个出现一个和为10的倍数
因为对于一个十位数,例如1X,这时候个位只有10 - 1 = 9才满足,对于一个三位数例如12X,则由于1和2是确定的,所以在120 - 129这十个数的范围内(也就是个位0 - 9)只有10 - 1 - 2 = 7,即127满足,对于大一点的数,例如637859X,6 + 3 + 7 + 8 + 5 + 9 = 38,因为最后一位肯定只能为正(不可能为-8),所以只有最后一位为40 - 38 = 2,即6378592符合条件,所有的数都这么看,会发现每次高位确定了,其实在个位上只有0 - 9当中的一个数能够满足,这就印证了num / 10的规律
最后只要注意下右边界就行了,即
0 - 90 -> 90 / 10 = 9个
但是
0 - 91 ->90 / 10 + 1 = 10个(由于91这个边界多加了一个)
处理方法是从90 / 10 * 10 = 90 -->91暴力扫一下,看有没有多出来一个能够满足各位和是10的倍数的,发现91是,所以就在9的基础上加1,因为我们证明了个位0 - 9有且只有一个数满足,所以只要扫过去发现一个直接返回就行了
#include <cstdio> #include <cstring> #include <iostream> using namespace std; long long get(long long num) { long long n = num / 10 * 10; bool flag = false; for (; n <= num; n++) { long long tn = n, sum = 0; while (tn) { sum += tn % 10; tn /= 10; } if (sum % 10 == 0) { flag = true; break; } } if (flag) return 1; else return 0; } long long solve(long long num) { if (num < 0) return 0; if (num < 10) return 1; return num / 10 + get(num); } int main() { int T; long long a, b; scanf("%d", &T); for (int t = 1; t <= T; t++) { scanf("%I64d%I64d", &a, &b); printf("Case #%d: %I64d\n", t, solve(b) - solve(a - 1)); } return 0; }