HDU 3709: Balanced Number (数位DP)

类型:数位DP

题意:定义平衡数为:以某位数为中心,左边的每位数*这个数离中心的距离 == 右边的每位数*这个数离中心的距离。问[x,y]之间有多少平衡数

思路:

做的莫名奇妙……

定义:dp[i][d][k][b] 为 首位为d的i位数,以第k位为中心点,平衡因子为b的数的个数。平衡因子定义为,中心点右边的和-中心点左边的和。

实际上这个状态定义冗余了。不需要定义首位d,同时,平衡因子如果定义成,之前所有数的加权和为b,那就不有写这么复杂了。

唉,现在有点乱。理不清楚啊。

#include <cstdio>
#include <cstring>
#include <iostream>
#define BB 1000
using namespace std;

long long dp[20][10][20][BB+BB];
int num[30];

long long dfs(int i, int d, int k, int b, bool isQuery) {
    #ifdef _D
    printf("(%d,%d,%d,%d,%d)
", i, d, k, b, isQuery);
    #endif
    if (k < 0) return 0;
    if (k >= BB+BB) return 0;
    long long &nowdp = dp[i][d][k][b];
    if (!isQuery && dp[i][d][k][b] != -1) {
        #ifdef _D
        printf("(%d,%d,%d,%d,%d)  ", i, d, k, b, isQuery);
        printf("return %d
", ((i-k)*d+BB == b));
        #endif
        return dp[i][d][k][b];
    }
    if (i == 1) {
        #ifdef _D
        printf("(%d,%d,%d,%d,%d)  ", i, d, k, b, isQuery);
        printf("return %d
", ((i-k)*d+BB == b));
        #endif
        return nowdp = ((i-k)*d+BB == b);
    }
    long long ans = 0;
    int nextB = b-(i-k)*d;
    int end = isQuery?num[i-1]:9;
    for (int j = 0; j <= end; j++) {
        ans += dfs(i-1, j, k, nextB, isQuery && j==end);
    }
    if (!isQuery) nowdp = ans;
    #ifdef _D
    printf("(%d,%d,%d,%d,%d)  ", i, d, k, b, isQuery);
    printf("return %d
", ans);
    #endif
    return ans;
}

long long cal(long long x) {
    if (x == -1) return 0;
    int len = 0;
    if (x == 0) {
        num[++len] = 0;
    } else {
        while (x) {
            num[++len] = x%10;
            x /= 10;
        }
    }
    long long ans = 0;
    for (int i = 1; i <= len; i++) {
        ans += dfs(len+1, 0, i, BB, true);
    }
    ans -= len-1; // 每种平衡点,都会算一次0这个数
    return ans;
}

int Nmain() {
    long long x;
    memset(dp, -1, sizeof(dp));
    //while (cin>>x) {
    long long pre = -1;
    for (int i = 0; i < 9999999; i++) {
        x = i;
        if (cal(x) >  pre+1) {
            cout<<x<<endl;
            pre = cal(x);
            getchar();
        }
        pre = cal(x);
    }
    return 0;
}

int main() {
    int t;
    scanf("%d", &t);
    memset(dp, -1, sizeof(dp));
    while (t--) {
        long long x, y;
        cin>>x>>y;
        cout<<cal(y)-cal(x-1)<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shinecheng/p/3597505.html