【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;
}
posted @ 2026-08-14 16:15  VLengu  阅读(2)  评论(0)    收藏  举报