Files
python/TangDou/AcWing/DP/ShuWei/HDU3709.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

61 lines
2.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}