题目描述
tabris有一个习惯,无聊的时候就会数圈圈,无论数字还是字母。
现在tabris更无聊啦,晚上睡不着觉就开始数羊,从a只数到b只。
顺便还数了a到b之间有多少个圈。
但是tabris笨啊,虽然数羊不会数错,但很可能数错圈的个数。
但是tabris很难接受自己笨这个事实,所以想问问你他一共应该数出多少个圈,这样tabris才好判断他到底笨不笨啊。
输入描述:
输入一个T,表示数据组数
每组测试数据包含两个正整数a,b。
T∈[1,1000]
a,b∈[1,1014]
输出描述:
每组数据输出结果,并换行。
示例1
输入
11 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 1 100
输出
0 0 0 1 0 1 0 2 1 1 111
备注:
数字的圈的个数请根据样例自行理解。
题解
数位$dp$。
$dp[i][j]$表示数字长度有$i$位,且第$i$位为$j$的总和,统计一下就可以了。
#include <bits/stdc++.h>
using namespace std;long long dp[16][10];
long long b[20], a[20];
long long c[20], sz;/*
0 1
1 0
2 0
3 0
4 1
5 0
6 1
7 0
8 2
9 1
*/void init() {memset(a, 0, sizeof a);a[0] = 1;a[4] = 1;a[6] = 1;a[8] = 2;a[9] = 1;b[0] = 1;for(int i = 1; i <= 15; i ++) {b[i] = b[i - 1] * 10LL;}for(int i = 0; i <= 9; i ++) {dp[1][i] = a[i];}for(int i = 2; i <= 15; i ++) {for(int j = 0; j <= 9; j ++) {dp[i][j] = a[j] * b[i - 1];for(int k = 0; k <= 9; k ++) {dp[i][j] = dp[i][j] + dp[i - 1][k];}}}
}long long get(long long x) {if(x == 0) return 0;long long ans = 0;sz = 0;while(x) {sz ++;c[sz] = x % 10;x = x / 10;}for(int i = 1; i <= sz - 1; i ++) {for(int j = 1; j <= 9; j ++) {ans = ans + dp[i][j];}}for(int j = 1; j < c[sz]; j ++) {ans = ans + dp[sz][j];}long long sum = a[c[sz]];for(int i = sz - 1; i >= 1; i --) {for(int j = 0; j < c[i]; j ++) {ans = ans + dp[i][j];ans = ans + sum * b[i - 1];}sum = sum + a[c[i]];}return ans;
}int main() {init();int T;scanf("%d", &T);while(T --) {long long L, R;scanf("%lld%lld", &L, &R);printf("%lld\n", get(R + 1) - get(L));}return 0;
}