題目鏈接:https://vjudge.net/problem/HDU-6156
題意:區間[L, R]的數,寫成k進制(l<=k<=r)後,如果是迴文串,那麼f(x,k)=k,否則f(x,k)=1,對f求和
題解:一看這種題就是數位dp,當時想的時候認爲,因爲要求是迴文串,所以前面的數是什麼對後面是有影響的,所以就不知道怎麼處理了,後來一想,在沒有限制的情況下,後面的數是隨便取的,所以也就是說,無論前面取的什麼數字,都能湊成迴文的,因此dp[ i ][ j ][ k ][bas] 表示到達第 i 位,迴文串開始的位置是 j ,是否還可以湊成迴文串 k ,幾進制 bas
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[35][35][2][38];
int w[35], len;
int num[35];
ll dfs(int pos, int state, int limit, int st, int lead, int bas) {
if(pos < 0) {
return state ? bas : 1;
}
if(!limit && dp[pos][st][state][bas] != -1) return dp[pos][st][state][bas];
int up = limit ? w[pos] : bas - 1;
ll res = 0;
for(int i = 0; i <= up; i++) {
num[pos] = i;
if(i == 0 && lead) res += dfs(pos - 1, state, limit && i == up, st - 1, 1, bas);
else if(i && lead) res += dfs(pos - 1, state, limit && i == up, st, 0, bas);
else {
if(pos >= (st + 1) / 2) res += dfs(pos - 1, state, limit && i == up, st, 0, bas);
else res += dfs(pos - 1, state && i == num[st - pos], limit && i == up, st, 0, bas);
}
}
if(!limit) dp[pos][st][state][bas] = res;
return res;
}
ll solve(ll x, int bas) {
len = 0;
while(x) {
w[len++] = x % bas;
x /= bas;
}
return dfs(len - 1, 1, 1, len - 1, 1, bas);
}
int main() {
int T;
int nn = 1;
ll l, r, L, R;
ll ans;
memset(dp, -1, sizeof(dp));
scanf("%d", &T);
while(T--) {
scanf("%lld %lld %lld %lld", &L, &R, &l, &r);
ans = 0;
for(int i = l; i <= r; i++)
ans += solve(R, i) - solve(L - 1, i);
printf("Case #%d: %lld\n", nn++, ans);
}
return 0;
}