HDU - 6156 Palindrome Function 數位dp

題目鏈接: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;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章