【LuoguP1831】杠杆数【数位DP】
链接
题目大意:
求l~r之中有多少杠杆数。其中杠杆数是以其中一位数为支点,两段数位到支点距离为权值,两边权值乘数字大小的和相等的数。
思路:
很容易想到数位DP来做这题,枚举之点的位置p,然后跑到第pos位时它的贡献就是(p - pos)*i,跑完sum=0就满足。
最后还要减去0的贡献。
code
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const ll MAXN = 11 * 18 * 18;
ll f[20][20][MAXN][2];
ll L, R;
ll lim[20], tot;
ll dfs(ll pos, ll p, ll sum, ll limit) {
if(pos == tot + 1) return sum == 0;
if(sum < 0) return 0;
if(~f[pos][p][sum][limit]) return f[pos][p][sum][limit];
ll ans = 0, up = limit ? lim[pos] : 9;
for(ll i = 0; i <= up; i ++)
ans += dfs(pos + 1, p, sum + i * (p - pos), limit && (i == up));
return f[pos][p][sum][limit] = ans;
}
ll Ans(ll n) {
ll x = n;
tot = 0;
memset(f, 0xff, sizeof(f));
while(x) {
lim[++ tot] = x % 10;
x /= 10;
}
for(ll i = 1; i <= tot / 2; i ++) swap(lim[i], lim[tot - i + 1]);
ll ans = 0;
for(ll i = 1; i <= tot; i ++) ans += dfs(1, i, 0, 1);
return ans - tot + 1;
}
int main() {
scanf("%lld%lld", &L, &R);
printf("%lld", Ans(R) - Ans(L - 1));
return 0;
}

浙公网安备 33010602011771号