|
|
#include <cstdio>
|
|
|
#include <cstring>
|
|
|
#include <iostream>
|
|
|
#include <cmath>
|
|
|
using namespace std;
|
|
|
typedef long long LL;
|
|
|
const int N = 20;
|
|
|
/*
|
|
|
x,y <= 10^{18},用10进制拆分到数组a,20位足够
|
|
|
本题对于内存空间的限制比较极限,如果无脑使用了32,就会使得f的容量超限
|
|
|
32*32*10010=10250240 byte = 10010 kb = 9.775390625 mb
|
|
|
内存上限是:65535kb=64mb
|
|
|
因为C++本身运行还需要一次的内存,64MB是很极限的,所以在多维数组创建时,一定要注意维度的上界
|
|
|
*/
|
|
|
LL a[N];
|
|
|
/*
|
|
|
pos:走到哪个数位,长度最长是N=20
|
|
|
k:以哪个数位为平衡数位,可以是1到20
|
|
|
sum:前面数位的数乘以偏移距离的和,最大偏移量是20,数位最大是9
|
|
|
可以视为
|
|
|
10*20+10*19+....+10*1=10*(1+2+3+...+20)=10*21*10=2100
|
|
|
*/
|
|
|
LL f[N][N][2110];
|
|
|
|
|
|
LL dfs(int pos, int k, int sum, bool lead, bool limit) {
|
|
|
if (pos == 0) return sum == 0;
|
|
|
if (sum < 0) return 0;
|
|
|
if (!lead && !limit && ~f[pos][k][sum]) return f[pos][k][sum];
|
|
|
int up = limit ? a[pos] : 9;
|
|
|
LL ans = 0;
|
|
|
for (int i = 0; i <= up; i++)
|
|
|
// sum + (pos - k) * i : 这句话很牛X,pos > k 是加,pos < k是减
|
|
|
ans += dfs(pos - 1, k, sum + (pos - k) * i, lead && i == 0, limit && i == a[pos]);
|
|
|
if (!limit && !lead) return f[pos][k][sum] = ans;
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
LL calc(LL x) {
|
|
|
if (x == -1) return 0; //如果输入的是l=0,则返回0
|
|
|
int al = 0;
|
|
|
while (x) a[++al] = x % 10, x /= 10;
|
|
|
LL ans = 0;
|
|
|
for (int i = al; i; i--) //枚举每一个数位,模拟此位置k为平衡数位
|
|
|
ans += dfs(al, i, 0, true, true);
|
|
|
// 00,000,0000......
|
|
|
return ans - al + 1;
|
|
|
}
|
|
|
int main() {
|
|
|
ios::sync_with_stdio(false);
|
|
|
cin.tie(0);
|
|
|
//平衡数是数的本身性质,与给定的区间无关,可以将memset放在循环外初始化
|
|
|
memset(f, -1, sizeof f);
|
|
|
int T;
|
|
|
cin >> T;
|
|
|
LL l, r;
|
|
|
while (T--) {
|
|
|
cin >> l >> r;
|
|
|
printf("%lld\n", calc(r) - calc(l - 1));
|
|
|
}
|
|
|
return 0;
|
|
|
} |