传送门
- 题意:求[A,B]之内的平衡数
- 0<=A<=B<=1e18
- 平衡数:以某个点为中心,两边的权值和相等。其中每一位的等于离中心的距离
∗
*
∗该位的数。例如4139以3为中心,左右两边权值和分别为
4
∗
2
+
1
∗
1
=
9
4*2+1*1=9
4∗2+1∗1=9和
9
∗
1
=
9
9*1=9
9∗1=9,即为平衡数。
- 特别的,0~9都是平衡数
- 题解:
- 首先一个平衡数只可能以一个数位为中心,递增不解释
- 枚举中心,然后某个数的权值和为0即为平衡数
- 因为权值和可正可负,为避免出现负数,设置key,最初另一个数的权值和为key,最后判断也判断是否等于key即可
- DP设置:dp[pos][mid][k1],k1表示mid一定时,某个数的权值和+key
- 注意事项:
- MLE: int可能能达到2e7或更大,但是ll达不到emm
- 这一题,枚举之后,我们多算了cnt-1次0,要减去。无论mid为多少,0总是满足,但是其他的数要为平衡数,只可能有一个mid。我们要减去0多枚举的cnt-1位
- 代码:
#include <cstring>
#include <iostream>
#include <string>
#define ll long long
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
int key = 2000;
ll dp[23][23][4010];
int a[23], cnt;
ll dfs(int pos, int mid, int k1, bool limit) {
if (pos == -1) return k1 == key;
if (!limit && dp[pos][mid][k1] != -1) return dp[pos][mid][k1];
ll res = 0;
int up = limit ? a[pos] : 9;
for (int i = 0; i <= up; i++) {
res += dfs(pos - 1, mid, k1 + (pos - mid) * i, limit && (i == a[pos]));
}
if (!limit) dp[pos][mid][k1] = res;
return res;
}
ll solve(ll x) {
if (x == -1) return 0;
cnt = 0;
while (x) {
a[cnt++] = x % 10;
x /= 10;
}
ll res = 0;
for (int i = 0; i < cnt; i++) {
res += dfs(cnt - 1, i, key, true);
}
return res - (cnt - 1);
}
signed main() {
memset(dp, -1, sizeof(dp));
int T;
cin >> T;
while (T--) {
ll l, r;
cin >> l >> r;
ll ans = solve(r) - solve(l - 1);
cout << ans << endl;
}
return 0;
}