首页 > 其他 > 详细

[HDU 6156] Palindrome Function

时间:2021-03-06 10:40:53      阅读:18      评论:0      收藏:0      [点我收藏+]

题意:
我们定义

\[ f(n, k)=\left\{ \begin{aligned} k& \ (n在k进制下为回文串) \1& \ (其余情况) \\end{aligned} \right.\]

\(\sum_{i=L}^{R}\sum_{j=l}^{r}f(i, j)\)

题解:
题意很明显往数位\(dp\)去靠,但是要求回文串,所以要记录下前面枚举的数位的数字是什么。同时要注意到前导\(0\)的情况,这会让你枚举的数字长度减少。并且只要有一个地方没有对应上,该串就无法形成回文串。我们定义\(dp[len][pos][k][good]\),代表当前枚举的数字长度为\(len + 1\),枚举到第\(pos\)位,在\(k\)进制下,之前对应位置的数字若能对应则\(good\)\(1\),其余置\(0\)时,能提供的贡献是多少。当我们枚举到数位到达当前长度的一半以及更长时,进行对应位置的判断,从而将状态转移下去。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll dp[37][37][37][2];
int pre[37], tot, n;
int a[37], cas;
int L, R, l, r;

ll dfs(int len, int pos, int k, int good, bool lim) {
	if (pos == -1) {
		if (good) return k;
		else return 1;
	}
	if (!lim && dp[len][pos][k][good]) {
		return dp[len][pos][k][good];
	}
	int to = lim? a[pos] : k - 1;
	ll tmp = 0;
	for (int i = 0; i <= to; ++i) {
		pre[pos] = i;
		if (i == 0 && len == pos && len) tmp += dfs(len - 1, pos - 1, k, good, lim && (i == to));
		else if (good && pos < (len + 1) / 2) tmp += dfs(len, pos - 1, k, i == pre[len - pos], lim && (i == to));
		else tmp += dfs(len, pos - 1, k, good, lim && (i == to));
	}
	if (!lim) dp[len][pos][k][good] = tmp;
	return tmp;
}

ll gao(int val, int k) {
	tot = 0;
	int v = val;
	while (v) {
		a[tot++] = v % k;
		v /= k;
	}
	return dfs(tot - 1, tot - 1, k, 1, true);
}

void solve() {
	scanf("%d %d %d %d", &L, &R, &l, &r);
	ll ans = 0;
	for (int k = l; k <= r; ++k) {
		ans += gao(R, k) - gao(L - 1, k);
	}
	printf("Case #%d: ", ++cas);
	printf("%lld\n", ans);
}

int main() {
	int t = 1;
	scanf("%d", &t);
	while (t--) solve();
	return 0;
} 

[HDU 6156] Palindrome Function

原文:https://www.cnblogs.com/Sstee1XD/p/14489230.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!