BZOJ 1833 数字计数(统计[a,b]每个数字出现次数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1833

题意:给定区间[a,b]。求区间内0到9每个数字出现的次数。

思路:f[i][j]表示到后i位是否全 0(j=1表示i位之前全0)这个状态某个数字出现的次数,p[i][j]表示这个状态后面有多少个数字。那么当前枚举到的数字为要统计的数字时,答案加 上后面还有多少种数字,即下一个状态的p值。那么我们枚举要统计的数字依次统计即可。

i64 f[20][2],p[20][2];
i64 n,m;
int a[20],aNum;

int cur;

pair<i64,i64> DFS(int dep,int flag,int allZero)
{
    if(dep==-1)  return MP(0,1);
    if(!flag&&f[dep][allZero]!=-1) return MP(f[dep][allZero],p[dep][allZero]);
    i64 x=0,y=0;
    int L=flag?a[dep]:9;
    int i;
    for(i=0;i<=L;i++)
    {
        pair<i64,i64> q=DFS(dep-1,flag&&(i==L),allZero&&(i==0));
        x+=q.first;
        y+=q.second;
        if(i==cur)
        {
            if(i==0&&!allZero||i!=0) x+=q.second;
        }
    }
    if(!flag)
    {
        f[dep][allZero]=x;
        p[dep][allZero]=y;
    }
    return MP(x,y);
}

i64 cal(i64 n,int x)
{
    if(n==0) return 0;
    cur=x; aNum=0;
    while(n)
    {
        a[aNum++]=n%10;
        n/=10;
    }
    pair<i64,i64> p=DFS(aNum-1,1,1);
    return p.first;
}

int main()
{
    RD(n); RD(m);
    i64 a[20]={0};
    int i;
    FOR0(i,10)
    {
        clr(f,-1);
        a[i]=cal(m,i)-cal(n-1,i);
    }
    printf("%lld",a[0]);
    FOR1(i,9) printf(" %lld",a[i]);
    puts("");
}

BZOJ 1833 数字计数(统计[a,b]每个数字出现次数),布布扣,bubuko.com

时间: 2024-11-08 21:08:36

BZOJ 1833 数字计数(统计[a,b]每个数字出现次数)的相关文章

【BZOJ 1833】 [ZJOI2010]count 数字计数

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 1697 Solved: 753 [Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

[BZOJ 1833] [ZJOI2010] count 数字计数 【数位DP】

题目链接:BZOJ - 1833 题目分析 数位DP .. 用 f[i][j][k] 表示第 i 位是 j 的 i 位数共有多少个数码 k . 然后差分询问...Get()中注意一下,如果固定了第 i 位,这一位是 t ,那么数码 t 的答案是要加一个值的(见代码). 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmat

BZOJ 1833: [ZJOI2010]count 数字计数( dp )

dp(i, j, k)表示共i位, 最高位是j, 数字k出现次数. 预处理出来. 差分答案, 对于0~x的答案, 从低位到高位进行讨论 ------------------------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 16; const int N =

【BZOJ】【1833】【ZJOI2010】count 数字计数

数位DP Orz iwtwiioi 学习了一下用记忆化搜索来捉题的新姿势……但没学会TAT,再挖个坑(妈蛋难道对我来说数位DP就是个神坑吗……sigh) 1 //BZOJ 1833 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i

1833: [ZJOI2010]count 数字计数

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2951  Solved: 1307[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

BZOJ_1833_[ZJOI2010]_数字计数_(数位dp)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1833 统计\(a~b\)中数字\(0,1,2,...,9\)分别出现了多少次. 分析 数位dp真是细节又多又容易出错,我都懒得看题解,所以也就懒得写题解了... 注意细节吧还是... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 ll a,b; 6 ll A[10],B[10],n

【BZOJ-1833】count数字计数 数位DP

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2494  Solved: 1101[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

[ZJOI2010][BZOJ1833] count 数字计数|模拟

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1976  Solved: 873[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义f[i][j][k]表示若前i个位置有k个j的此时的全局方案数,然后就可以记忆化搜索了(具体看代码吧) 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath>