题面
题目链接
大秦 为你打开 题目传送门
备用题面
定义平衡数:对于出现的数字,奇数数字出现偶数次,偶数数字出现奇数次。
比如 77, 211, 6222 和 112334445555677 都是平衡数,而 351, 21, 和 662 都不是
请统计 $[N,M]$ 区间内的平衡数的个数。
思路
首先这是一道数位 DP 题。我们考虑统计每一种数字的出现次数($0$ ~ $9$),但是肯定不可以直接统计数量,我们可以考虑进制压缩。我们这里使用 $3$ 进制,因为我们要考虑没有,有奇数,有偶数的情况。而不用二进制的原因是,没有和有偶数是不一样的。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| #include<bits/stdc++.h> using namespace std;
typedef unsigned long long ll;
namespace FastIO { template<typename T> inline T read(T& x) { x = 0; int f = 1; char ch; while (!isdigit(ch = getchar())) if (ch == '-') f = -1; while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar(); x *= f; return x; } template<typename T, typename... Args> inline void read(T& x, Args &...x_) { read(x); read(x_...); return; } inline ll read() { ll x; read(x); return x; } }; using namespace FastIO;
ll N, M;
int a[30]; int p[30]; ll dp[30][60050][3];
inline void Input() { scanf("%llu%llu", &N, &M); }
inline int Check(int mask) { for(int i = 0; i <= 9; i++) { int now = mask / p[i] % 3; if(now == 0) continue; if((now & 1) == (i & 1)) return 0; } return 1; }
inline int Change(int mask, int x) { int now = mask / p[x] % 3; if(now == 0) mask += p[x]; else if(now == 1) mask += p[x]; else if(now == 2) mask -= p[x]; return mask; }
inline ll Dfs(int len, int limit, int top, int mask) { if(len == 0) return Check(mask); if(!limit && dp[len][mask][top] != -1) return dp[len][mask][top]; int mx = limit ? a[len] : 9; ll ans = 0; for(int i = 0; i <= mx; i++) { ans += Dfs( len - 1, limit && i == a[len], top && i == 0, (top && !i) ? 0 : Change(mask, i) ); } if(!limit) dp[len][mask][top] = ans; return ans; }
inline ll Calc(ll x) { int len = 0; while(x) { a[++len] = x % 10; x /= 10; } return Dfs(len, 1, 1, 0); }
inline void Work() { memset(dp, -1, sizeof(dp)); p[0] = 1; for(int i = 1; i <= 10; i++) { p[i] = p[i - 1] * 3; } printf("%llu", Calc(M) - Calc(N - 1)); }
int main() { int T = 1; while(T--) { Input(); Work(); } return 0; }
|