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 occurrences of each digit. For example, if
a = 1024 and b = 1032, the list will be

1024 1025 1026 1027 1028 1029 1030 1031 1032

there are ten 0‘s in the list, ten 1‘s, seven 2‘s, three 3‘s, and etc.

Input

The input consists of up to 500 lines. Each line contains two numbers
a and b where
0 < a, b < 100000000. The input is terminated by a line `0 0‘, which is not considered as part of the input.

Output

For each pair of input, output a line containing ten numbers separated by single spaces. The first number is the number of occurrences of the digit 0, the second is the number of occurrences of the digit 1, etc.

Sample Input

1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0

Sample Output

1 2 1 1 1 1 1 1 1 1
85 185 185 185 190 96 96 96 95 93
40 40 40 93 136 82 40 40 40 40
115 666 215 215 214 205 205 154 105 106
16 113 19 20 114 20 20 19 19 16
107 105 100 101 101 197 200 200 200 200
413 1133 503 503 503 502 502 417 402 412
196 512 186 104 87 93 97 97 142 196
398 1375 398 398 405 499 499 495 488 471
294 1256 296 296 296 296 287 286 286 247

Source

Root :: AOAPC II: Beginning Algorithm Contests (Second Edition) (Rujia Liu) :: Chapter 10. Maths ::
Examples

Submit
Status

统计区间里0到9每个数字出现了多少次,直接数学瞎搞

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10 + 10;
typedef long long ll;
#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)
typedef long long ll;
int c[maxn][maxn];
void init(int n)
{
    for(int i = 0; i <= n; i++) {
        c[i][0] = 1;
        for(int j = 1; j <= i; j++) c[i][j] = c[i-1][j-1] + c[i-1][j];
        c[i][i+1] = 0;
    }
}
ll quick(int a,int n)
{
    ll res = 1,b = a;
    while(n>0) {
        if(n&1)res *= b;
        b = b*b;
        n>>=1;
    }
    return res;
}
ll work(int f,int k,int L,int tot)/*计算以f开头长为L且之前已经出现tot个k的数字里有多少个k*/
{
    ll res = 0;
    if(f==k)tot++;
    for(int i = 0; i < L; i++) {
        res += (i+tot)*c[L-1][i]*quick(9,L-1-i);
    }
    return res;
}
ll solve(const char *s,int k)/*计算[1,s)里的数字一共有多少个k*/
{
    int sz = strlen(s);
    ll res = 0,tot = 0;
    for(int i = 1; i < s[0]-'0'; i++)res += work(i,k,sz,0);
    for(int L = 1; L < sz; L++) {
        for(int i = 1; i < 10; i++)
            res += work(i,k,L,0);
    }
    if(s[0]-'0'==k)tot++;
    for(int i = 1; i < sz; i++) {
        int limt = s[i] - '0';
        for(int j = 0; j < limt; j++) {
            res += work(j,k,sz-i,tot);
        }
        if(limt==k)tot++;
    }
    return res;
}
int main()
{
    init(12);
    int L,R;
    while(~scanf("%d%d",&L,&R)) {
        if(L+R==0)return 0;
        if(L>R)swap(L,R);
        char sl[20],sr[20];
        sprintf(sl,"%d",L);
        sprintf(sr,"%d",R+1);
        for(int i = 0; i < 10; i++)
            printf("%lld%c",solve(sr,i)-solve(sl,i)," \n"[i==9]);
    }
    return 0;
}
时间: 2024-08-13 18:53:43

UVA 1640(数位统计)的相关文章

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

[ACM] ural 1057 Amount of degrees (数位统计)

1057. Amount of Degrees Time limit: 1.0 second Memory limit: 64 MB Create a code to determine the amount of integers, lying in the set [X;Y] and being a sum of exactlyK different integer degrees of B. Example. Let X=15, Y=20, K=2, B=2. By this exampl

UVa 1640 The Counting Problem (数位DP)

题目 题目大意 给出\(a\).\(b\), 统计\(a\)和\(b\)(包含\(a\)和\(b\))之间的整数中, 数字\(0, 1, 2, 3, 4, 5, 6, 7, 8, 9\)分别出现了多少次.\(1 ≤ a, b ≤ 10^8\).注意, \(a\)有可能大于\(b\). 题解 设\(f_d(n)\)表示\(0 \cdots n\)中数字\(d\)出现的个数, 则求的是\(f_d(a) - f_d(b - 1)\). 暴力显然是会\(TLE\)的, 我们可以分段来求.例如我们要求\(

URAL 1057 Amount of Degrees(数位统计)

题意:  求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K 个互不相等的B的整 数次幂之和. 思路:对于二进制来说(图片摘自刘聪的浅谈数位类统计问题论文) 现在推广到b进制 因为对于b进制的每一位,我们只需要讨论这一位是否是一,所以我们可以把这个数转换为一个等价的二进制数, 方法是将这个数从左到右第一位不是零或一的位变为1,并把其右边的所有位置一,求出这个二进制数. #include<cstdio> #include<cstring> #include<cm

UVa 1640 (计数) The Counting Problem

题意: 统计[a, b]或[b, a]中0~9这些数字各出现多少次. 分析: 这道题可以和UVa 11361比较来看. 同样是利用这样一个“模板”,进行区间的分块,加速运算. 因为这里没有前导0,所以分块的时候要多分几种情况. 以2345为例,这是一个四位数,首先要计算一下所有的一位数.两位数以及三位数各个数字出现的个数. 对应的模板分别为n,n*,n**,其中n代表非零数字,*代表任意数字. 考虑这样一个长为l的模板****(l个*),这样的数共10l个,而且各个数字都是等频率出现,所以每个数

UVA 1640 The Counting Problem

https://vjudge.net/problem/UVA-1640 题意:统计区间[l,r]中0——9的出现次数 数位DP 注意删除前导0 #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int ans[10],a[10],dp[10][10],bit[10]; int dfs(int dep,int ty,bool l

UVa 1640 - The Counting Problem(数论)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4515 题意: 给出整数a.b,统计a和b(包含a和b)之间的整数中,数字0,1,2,3,4,5,6,7,8,9分别出现了多少次.1≤a,b≤1e8. 分析: 解决这类题目的第一步一般都是:令f(n,d)表示0-n中数字d出现的次数,则所求的就是f(b,d)-f(a-1,d).例如,

UVa1640 - The Counting Problem(数位统计)

题意: 统计两个整数a,b之间各个数字(0~9)出现的次数,如1024和1032,他们之间的数字有1024 1025 1026 1027 1028 1029 1030 1031 1032 总共有10个0,10个1,3个3等等. 分析: 因为前导0的干扰,为了计算方便暂时都先计算在内,之后再减; 如果是0~199,那么百位上的0和1各出现一次,s剩下的就是两个00~99,总共两百个二位数,而每个数出现的次数都一样,都是2*(99-00+1)/10; 那么任意的数都可以分解成类似的数字,如3426,

[uva 1350]数位dp+二分

题目链接:https://vjudge.net/problem/38405 #include<bits/stdc++.h> using namespace std; long long dp[64][2]; int b[64]; long long dfs(int pos,int preok,int pre1) { if (pos==-1) return 1; if (preok && dp[pos][pre1]!=-1) return dp[pos][pre1]; int u