[ZJOI 2010] 数字计数
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1833
[算法]
数位DP
[代码]
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; int i; long long a,b; long long f[15][10][15]; inline void dp(long long m) { long long i,j,k,x; memset(f,0,sizeof(f)); f[0][0][0] = 1; for (i = 1; i <= 12; i++) { for (j = 0; j <= 9; j++) { for (k = 0; k <= i; k++) { if (j != m) { for (x = 0; x <= 9; x++) f[i][j][k] += f[i - 1][x][k]; } else if (k >= 1) { for (x = 0; x <= 9; x++) f[i][j][k] += f[i - 1][x][k - 1]; } } } } } inline long long calc(long long x,long long t) { long long i,j,k,len = 0; long long res = 0; long long cnt = 0; long long a[12]; memset(a,0,sizeof(a)); while (x != 0) { a[++len] = x % 10; x /= 10; } reverse(a + 1,a + len + 1); for (i = 2; i <= len; i++) { for (j = 1; j <= 9; j++) { for (k = 1; k <= len - i + 1; k++) res += f[len - i + 1][j][k] * k; } } for (i = 1; i <= len; i++) { for (j = 0; j < a[i]; j++) { if (i == 1 && !j) continue; for (k = cnt; k <= len; k++) { res += f[len - i + 1][j][k - cnt] * k; } } if (a[i] == t) cnt++; } return res; } int main() { while (scanf("%lld%lld",&a,&b) && (a || b)) { if (a > b) swap(a,b); for (i = 0; i < 9; i++) { dp(i); printf("%lld ",calc(b + 1,i) - calc(a,i)); } dp(9); printf("%lld\n",calc(b + 1,9) - calc(a,9)); } return 0; }