HDU6156 Palindrome Function数位dp

题意:求L~R所有的数的l~r进制的f(x,k进制), 如果x是回文串f(x,k进制) = k, 否则等于1;

枚举进制,求出每一种情况,注意膜k,不是膜10,T_T调了好久才发现错在这;

题解:dp[pos][start][similar][basic]表示basic进制下,处理到完pos位,从start位开始,similar状态下回文串的个数。则记忆化搜索下即可。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int dp[32][32][2][37];
int tmp[32], dight[32];

int dfs(int pos, int start, bool similar, bool limit, int basic)
{
    if(!pos) return similar;
    int &A = dp[pos][start][similar][basic];
    if(~A && !limit) return A;
    int up = limit ? dight[pos] : basic - 1, res = 0;
    for(int i = 0;i <= up;i ++) {
        tmp[pos]  = i;
        if(i == 0 && pos == start) {
            res += dfs(pos-1, start-1, similar, limit && i == dight[pos], basic);
        } else if(similar && pos < start / 2 + 1) {
            res += dfs(pos-1, start, similar && i == tmp[start+1-pos], limit && i == dight[pos], basic);
        } else {
            res += dfs(pos-1, start, similar, limit && i == dight[pos], basic);
        }
    }
    if(!limit) A = res;
    return res;
}

int solve(int n, int k)
{
    int cnt = 0;
    while(n) {
        dight[++cnt] = n % k;
        n /= k;
    }
    return dfs(cnt, cnt, 1, 1, k);
}
int main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    int T, Case = 0;
    int L, R, l, r;
    memset(dp, -1, sizeof(dp));
    cin >> T;
    while(T --) {
        cin >> L >> R >> l >> r;
        ll res = 0;
        for(int i = l;i <= r;i ++) {
            ll t = solve(R, i) - solve(L-1, i);
            res += t * i + R - L + 1 - t;
        }
        cout << "Case #" << ++Case << ": ";
        cout << res << '\n';
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_36876305/article/details/80469228