[HDOJ6156] Palindrome Function(数位dp, 枚举)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6156

题意:算十进制下数字在[L,R]内用[l,r]进制表述下的数字贡献。

贡献有两种:回文数,贡献是进制k;不是回文数,贡献是1。

由于进制只有36个,枚举进制分别做统计回文数的数位dp即可,贡献按要求。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int maxn = 1010;
 6 const int maxm = 55;
 7 const LL mod = 1e9+7;
 8 int digit[maxn], revert[maxn];
 9 LL L, R, l, r;
10 LL dp[maxm][maxm][maxn][2];
11 
12 LL dfs(int k, int s, int l, bool ok, bool flag) {
13     if(l < 0) {
14         if(ok) return k;
15         return 1;
16     }
17     if(!flag && ~dp[k][s][l][ok]) return dp[k][s][l][ok];
18     int pos = flag ? digit[l] : k - 1;
19     LL ret = 0;
20     for(int i = 0; i <= pos; i++) {
21         revert[l] = i;
22         if(i == 0 && s == l) {
23             ret += dfs(k, s-1, l-1, ok, flag&&(i==pos));
24         }
25         else if(ok && l < (s + 1) / 2) {
26             ret += dfs(k, s, l-1, i==revert[s-l], flag&&(i==pos));
27         }
28         else {
29             ret += dfs(k, s, l-1, ok, flag&&(i==pos));
30         }
31     }
32     if(!flag) dp[k][s][l][ok] = ret;
33     return ret;
34 }
35 
36 LL f(LL n, LL k) {
37     if(n == 0) return k;
38     int pos = 0;
39     while(n) {
40         digit[pos++] = n % k;
41         n /= k;
42     }
43     return dfs(k, pos-1, pos-1, 1, 1);
44 }
45 
46 
47 signed main() {
48     // freopen("in", "r", stdin);
49     int T, _ = 1;
50     scanf("%d", &T);
51     memset(dp, -1, sizeof(dp));
52     while(T--) {
53         scanf("%lld%lld%lld%lld",&L,&R,&l,&r);
54         LL ret = 0;
55         for(int i = l; i <= r; i++) {
56             ret += f(R, i) - f(L-1, i);
57         }
58         printf("Case #%d: %lld\n", _++, ret);
59     }
60     return 0;
61 }

 

posted @ 2017-08-19 21:05  Kirai  阅读(384)  评论(0编辑  收藏  举报