[洛谷P2602][ZJOI2010]數字計數
阿新 • • 發佈:2018-11-01
題目大意:求區間$[l,r]$中數字$0\sim9$出現個數
題解:數位$DP$
卡點:無
C++ Code:
#include <cstdio> #include <iostream> struct node { long long s[10], sum; inline node() {for (register int i = 0; i < 10; i++) s[i] = 0; sum = 0;} inline node(int x) {for (register int i = 0; i < 10; i++) s[i] = 0; sum = x;} inline friend node operator + (const node &lhs, const node &rhs) { node res; res.sum = lhs.sum + rhs.sum; for (register int i = 0; i < 10; i++) res.s[i] = lhs.s[i] + rhs.s[i]; return res; } inline friend node operator - (const node &lhs, const node &rhs) { node res; res.sum = lhs.sum - rhs.sum; for (register int i = 0; i < 10; i++) res.s[i] = lhs.s[i] - rhs.s[i]; return res; } inline friend std::ostream & operator << (std::ostream &Fout, const node __node) { for (register int i = 0; i < 10; i++) { Fout << __node.s[i]; Fout << (i == 9 ? '\n' : ' '); } return Fout; } }; int num[20], tot; node f[20]; bool vis[20]; node calc(int x, int lim, int lead) { if (!x) return node(1); if (!lim && lead && vis[x]) return f[x]; node F; for (int i = lim ? num[x] : 9, op = 1; ~i; i--, op = 0) { node tmp = calc(x - 1, lim && op, lead || i); F = F + tmp; if (i || lead) F.s[i] += tmp.sum; } if (!lim && lead) f[x] = F, vis[x] = true; return F; } node solve(long long x) { if (x < 0) return node(); tot = 0; while (x) { num[++tot] = x % 10; x /= 10; } return calc(tot, 1, 0); } long long l, r; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> l >> r; std::cout << solve(r) - solve(l - 1) << std::endl; return 0; }