UVa 1640 (计数) The Counting Problem

题意:

统计[a, b]或[b, a]中0~9这些数字各出现多少次。

分析:

这道题可以和UVa 11361比较来看。

同样是利用这样一个“模板”,进行区间的分块,加速运算。

因为这里没有前导0,所以分块的时候要多分几种情况。

以2345为例,这是一个四位数,首先要计算一下所有的一位数、两位数以及三位数各个数字出现的个数。

对应的模板分别为n,n*,n**,其中n代表非零数字,*代表任意数字。

考虑这样一个长为l的模板****(l个*),这样的数共10l个,而且各个数字都是等频率出现,所以每个数字出现的次数为l * 10l-1

统计完三位数一下的数字之后,就开始统计四位数字:1***,20**,21**,22**,230*,231*,232*,233*,2340,2341,2342,2343,2344,2345

在统计每个模板时,分这样两块计算:

  • **中该数字出现的次数
  • 前面该数出现的次数,比如22**,前面两个2会重复102

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 int pow10[10], cnt[10];
 7
 8 int f(int d, int n)
 9 {
10     char s[15];
11     sprintf(s, "%d", n);
12     int len = strlen(s);
13     int ans = 0;
14
15     for(int i = 1; i < len; i++)
16     {
17         if(i == 1) { ans++; continue; }
18         ans += 9 * cnt[i - 1];
19         if(d > 0) ans += pow10[i - 1];
20     }
21
22     int pre[10];
23     for(int i = 0; i < len; i++)
24     {
25         pre[i] = (int)(s[i] - ‘0‘ == d);
26         if(i) pre[i] += pre[i - 1];
27     }
28
29     for(int i = 0; i < len; i++)
30     {
31         int maxd = s[i] - ‘0‘ - 1;
32         int mind = 0;
33         if(i == 0 && len > 1) mind = 1;
34         for(int digit = mind; digit <= maxd; digit++)
35         {
36             ans += cnt[len - i - 1];
37             if(i) ans += pre[i - 1] * pow10[len - i - 1];
38             if(digit == d) ans += pow10[len - i - 1];
39         }
40     }
41     return ans;
42 }
43
44 int main()
45 {
46     //freopen("in.txt", "r", stdin);
47
48     pow10[0] = 1;
49     for(int i = 1; i <= 8; i++)
50     {
51         pow10[i] = pow10[i - 1] * 10;
52         cnt[i] = pow10[i - 1] * i;
53     }
54
55     int a, b;
56     while(scanf("%d%d", &a, &b) == 2 && a && b)
57     {
58         if(a > b) swap(a, b);
59         for(int d = 0; d <= 9; d++)
60         {
61             if(d) printf(" ");
62             printf("%d", f(d, b+1) - f(d, a));
63         }
64         printf("\n");
65     }
66
67     return 0;
68 }

代码君

时间: 2024-10-25 06:51:47

UVa 1640 (计数) The Counting Problem的相关文章

UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。

/** 题目:UVA 1640 The Counting Problem UVA1640 链接:https://vjudge.net/problem/UVA-1640 题意:求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数. 思路:数位dp: dp[leadzero][i][j][k]表示前面是否选过非0数,即i长度之后可以第一个出现0,而不是前导0,长度为i,前面出现j,k次,j出现的次数. */ #include<iostream> #include<cstri

POJ 2282-The Counting Problem(组合数学_区间计数)

The Counting Problem Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2282 Appoint description:  System Crawler  (2015-04-15) Description Given two integers a and b, we write the numbers between

UVa 729 - The Hamming Distance Problem

题目:构造n位01串,其中有m个1的所有组合. 分析:搜索.枚举.可以利用库函数,求解,也可以利用dfs求解:我这里采用位运算计算组合数. 说明:注意库啊! #include <iostream> #include <cstdlib> #include <cstdio> using namespace std; int S[20]; int main() { int T,N,M; while ( cin >> T ) for ( int t = 1 ; t

洛谷——P1596 [USACO10OCT]湖计数Lake Counting

P1596 [USACO10OCT]湖计数Lake Counting 题目描述 Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W'

HDOJ 1663 The Counting Problem 打表

先打出0~8位数,分别可以被整十/百/千/万...整除时 , 各个数字出现了几次的表 先把每要查询的数字的每一位在表里查询得到一个结果 但是这样是不全面的,考虑这样的情况: 例如2345这样的数 234* 这种情况下 4出现了5次 23**这种情况下3出现了45次 2***中2出现了345次等.....从后往前扫一遍即可 其中0的情况比较特殊,简单的扫一遍会漏掉很多可能 比如 5050时: 500*的情况下,第2个0就没有考虑到,所以还要进行一次补0的操作. 排除首位从前往后扫,遇到每一个不为0

UVA - 10239 The Book-shelver&#39;s Problem

Description Problem D The Book-shelver's Problem Input: standard input Output: standard output Time Limit: 5 seconds Memory Limit: 32 MB You are given a collection of books, which must be shelved in a library bookcase ordered (from top to bottom in t

UVA 1640(数位统计)

The Counting Problem Time Limit:3000MS   Memory Limit:Unknown   64bit IO Format:%lld & %llu SubmitStatus Description Given two integers a and b, we write the numbers between a and b, inclusive, in a list. Your task is to calculate the number of occur

POJ 2282 The Counting Problem,组合数学

POJ 2282 The Counting Problem,组合数学 ACM 题目地址:POJ 2282 题意: 给出俩数n,m,求从n~m中0~9分别出现的次数. 分析: 组合数学. 只要能快速算出0~n中各个数的出现次数就能解决问题了. 要把数拆开来看,比如3456=3000+400+50+6. 然后就只要考虑后面都是0的数就行了. 0~3000中,我们要分为两部分来考虑: 在第一位中,0\1\2都出现了1000次. 假设不管第一位,后面那些位数出现0~9的几率是均等的(先不考虑前导0).那

uva 10245 The Closest Pair Problem (暴力+剪枝)

uva 10245 The Closest Pair Problem 题目大意:给出n个点,求出距离最近的两点间的距离.若点与点间的距离都大于10000,输出INFINITY 解题思路:这题的正统做法是分治,偷懒方法是暴力加剪枝.先按x坐标排序,然后fabs(p[i] - p[j]) > ans的点就可以直接跳过了. #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algori