题意:给定两个数m, n,求从 m 到 n 中0-9数字各出现了多少次。
析:看起来挺简单的,其实并不好做,因为有容易想乱了。主要思路应该是这样的,分区间计数,先从个位进行计,一步一步的计算过来。都从0开始,最后用大数减小数的即可。
举个例子吧,容易理解。比如0-1234。
先计算个位数字,有1-4,然后计算123各出现了5次,注意是这里是5次,不是4次,因为我们要加上那个0,然后就剩下那个1230了,我们想那么现在个位数从开始到这,
重复了123次,然后再进行下一位,依次进行,直到0.
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <functional> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <deque> #include <map> #include <cctype> #include <stack> #include <sstream> #include <cstdlib> #define freopenr freopen("in.txt", "r", stdin) #define freopenw freopen("out.txt", "w", stdout) using namespace std; #include <ctime> typedef long long LL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const LL LNF = 0x3f3f3f3f3f; const double inf = 0x3f3f3f3f3f3f; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1e5 + 5; const int mod = 1e9 + 7; const char *mark = "+-*"; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, 1, 0, -1}; int n, m; inline int Min(int a, int b){ return a < b ? a : b; } inline int Max(int a, int b){ return a > b ? a : b; } inline LL Min(LL a, LL b){ return a < b ? a : b; } inline LL Max(LL a, LL b){ return a > b ? a : b; } int ans[15]; void dfs(int n, int m, int ok){ if(-1 == n) return ; int x = n / 10; int y = n % 10; for(int i = 1; i <= y; ++i) ans[i] += ok * m; for(int i = 0; i < 10; ++i) ans[i] += ok * m * x; int tmp = x; while(tmp){ ans[tmp%10] += ok * (y+1) * m; tmp /= 10; } dfs(x-1, m*10, ok); } int main(){ while(scanf("%d %d", &m, &n) == 2){ if(!m && !n) break; if(m < n) swap(m, n); --n; memset(ans, 0, sizeof ans); dfs(m, 1, 1); dfs(n, 1, -1); for(int i = 0; i < 10; ++i){ if(i) putchar(' '); printf("%d", ans[i]); } printf(" "); } return 0; }