uva1640(数位统计)

来源:互联网 发布:索尼xz网络设置 编辑:程序博客网 时间:2024/05/16 08:13
/*translation:给出整数a,b。统计a和b之间的整数中,数字0,1,2,3...9出现的个数各是多少?并打印出来。solution:1:由于数据范围太大,直接一次统计过去肯定超时,所以解决方法是按照每1000个数划分成一个区间,依次对每个区间进行统计累加。这样以来就能将10^8的数据量变成10^6的数据量,1s内绰绰有余。2:定义千位及以上的为高位数,以下的为低位数。先写个小程序,对每1000个数的区间进行观察,可以发现每个区间内的每个数出现的次数都为300.但是如果某个数一旦在高位数中出现,就意味着要多加上1000,因为高位数在这个区间内一直不变,所以出现次数多了1000。3:为了统计方便,每个区间的开头跟结尾都定义成1000的倍数。然后[a,b]区间内有遗漏的少部分数用暴力统计累加。note:1:注意对每段区间开始统计的时候要在开始位置加上1000,不然到了最后即使p, b之间相差不到1000也会统计,相当与多统计了1次2:因为在开始多加了1000,所以在这里减去1000的意思是对“上一段的区间”的高位数进行统计。这道题可以总结出一个数位统计的方法。date:2016.10.9*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = 1e8;typedef long long ll;ll cnt[10], res[10];int a, b;void output() {cout << cnt[0];for(int i = 1; i <= 9; i++)cout << " " << cnt[i];cout << endl;}int main(){//freopen("in.txt", "r", stdin);while(cin >> a >> b && a && b) {memset(cnt, 0, sizeof(cnt));memset(res, 0, sizeof(res));if(a > b)swap(a, b);if(b < 1000) {//数据量少的直接统计for(int i = a; i <= b; i++) {int x = i;while(x) {cnt[x % 10]++;x /= 10;}}} else {int s = a / 1000;if(s)s *= 1000;elses = 1000;//求得最开始的那个区间的起始位置int p;//对每个区间进行统计for(p = s + 1000; p <= b; p += 1000) {//note1for(int i = 0; i <= 9; i++)cnt[i] += 300;int x = (p-1000) / 1000;//note2while(x) {cnt[x % 10] += 1000;x /= 10;}}for(int i = p-1000; i <= b; i++) {int x = i;while(x) {cnt[x % 10]++;x /= 10;}}if(s > a) {for(int i = a; i < s; i++) {int x = i;while(x) {res[x % 10]++;x /= 10;}}} else {for(int i = s; i < a; i++) {int x = i;while(x) {res[x % 10]--;x /= 10;}}}for(int i = 0; i <= 9; i++) cnt[i] += res[i];}output();}    return 0;}

1 0
原创粉丝点击