题意:问[L, R]内有多少数字,满足每个奇数都出现了偶数次,每个偶数都出现了奇数次(没有出现的数不考虑)
用三进制来表示状态,0表示没出现,1表示出现奇数次,2表示出现偶数次。
然后就是裸的数位DP了。
/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 20, maxm = 59055;
int dig[maxn], ter[maxn];
ULL dp[maxn][maxm];
template <class numtype>
inline void read(numtype &x) {
int f = 0; x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? 1 : 0;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
if(f) x = -x;
}
inline bool check(int s) {
for(int i = 0; i <= 9 && s; i++, s /= 3) {
int k = s % 3;
if(!k) continue;
if((i & 1) && (k & 1)) return 0;
if((~i & 1) && (~k & 1)) return 0;
}
return 1;
}
inline int newst(int s, int x) {
int k = (s / ter[x]) % 3;
s -= k * ter[x];
if(!k) k = 1;
else k = 3 - k;
return s += k * ter[x];
}
inline ULL dfs(int pos, int state, bool limit, bool zero) {
if(pos == 0) return check(state);
if(!limit && !zero && ~dp[pos][state]) return dp[pos][state];
int upb = limit ? dig[pos] : 9;
ULL res = 0;
for(int i = 0; i <= upb; i++)
res += dfs(pos - 1, (zero && !i) ? 0 : newst(state, i), limit && i == dig[pos], zero && !i);
if(!limit && !zero) dp[pos][state] = res;
return res;
}
inline ULL calc(ULL x) {
int top = 0;
for(; x; x /= 10) dig[++top] = x % 10;
return dfs(top, 0, 1, 1);
}
int main() {
int T; ULL l, r;
memset(dp, -1, sizeof(dp));
ter[0] = 1;
for(int i = 1; i <= 9; i++) ter[i] = (ter[i - 1] << 1) + ter[i - 1];
for(read(T); T; T--) {
read(l); read(r);
printf("%llu\n", calc(r) - calc(l - 1));
}
return 0;
}