【题目链接】
题意:问[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; }