要求m-n内在l-r进制下的是回文数的总个数。
dp[进制][从第j为开始][目前到达第k位] = 总的方案数
dfs枚举目前的到达的位置,这个数开始的位置,进制,前导零,限制条件,然后枚举的时候如果我现在是总的数的前一半,那么我就可以随意枚举,如果我已经到这个数的后一半了,那么我枚举的数字应该要满足和前面一半的这个位置对应的数,否则的话就是不满足条件的回文数,用这个数开始的位置为0来表示这个数不满足条件或者说我枚举的这个数全部都是零。然后算出这个区间内的回文数,要求sumf(i, j), 那么就是这里面的回文数乘k+不是回文数的值。

#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100005; const int maxm = 1000005; const int mod = 10007; using namespace std; int T, tol; ll n, m; int digit[100]; ll tmp[100]; ll dp[40][100][100]; ll dfs(int pos, int st, int k, bool lead, bool limit) { if(pos == 0) return st ? 1 : 0; if(dp[k][st][pos] != -1 && !limit) return dp[k][st][pos]; ll ans = 0; int up = limit ? digit[pos] : k-1; for(int i=0; i<=up; i++) { tmp[pos] = i; if(lead && i == 0) ans += dfs(pos-1, st-1, k, lead, limit && i==digit[pos]); else if(pos > st/2) ans += dfs(pos-1, st, k, 0, limit && i==digit[pos]); else ans += dfs(pos-1, i==tmp[st-pos+1] ? st : 0, k, 0, limit && i== digit[pos]); } if(!limit) dp[k][st][pos] = ans; return ans; } ll solve(ll n, int k) { memset(digit, 0, sizeof digit); int pos = 1; while(n) { digit[pos++] = n % k; n /= k; } return dfs(pos-1, pos-1, k, 1, 1); } int main() { int cas = 1; scanf("%d", &T); memset(dp, -1, sizeof dp); while(T--) { int l, r; scanf("%I64d%I64d%d%d", &m, &n, &l, &r); m--; ll ans = 0; for(int i=l; i<=r; i++) { ll cnt1 = solve(n, i); ll cnt2 = solve(m, i); ans += (cnt1 - cnt2)*i + (n-m+cnt2-cnt1); } printf("Case #%d: %I64d ", cas++, ans); } return 0; }