zoukankan      html  css  js  c++  java
  • BZOJ1833: [ZJOI2010]count 数字计数

    BZOJ1833: [ZJOI2010]count 数字计数

    Description

    给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

    Input

    输入文件中仅包含一行两个整数a、b,含义如上所述。

    Output

    输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

    Sample Input

    1 99

    Sample Output

    9 20 20 20 20 20 20 20 20 20

    HINT

    30%的数据中,a<=b<=10^6;
    100%的数据中,a<=b<=10^12。


    题解Here!

    一眼看出是数位$DP$。
    然后也一眼看出不会做。。。
    一脸无奈。。。
    开始乱搞。。。
    然后真的把数位$DP$搞出来了。。。
    开森!
    设$dp[i][j][k]$表示一个长度为$i$的数,其中最高位是$j$,$kk$这个数码一共出现的次数。
    然后我们需要枚举当前位数,当前最高位填什么数,次高位填什么数,之后转移一下就好了。
    转移方程长这个样:
    $$dp[i][j][p]=sum_{k=0}^9dp[i-1][k][p]$$
    这不就做完了
    吗?
    没有!
    我们填上的最高位可是出现了很多次,但是一次都没有被记录进去。。。
    这不就尴尬了?
    好办,我们让剩下的$i-1$为随意选择只考虑当前最高位上出现的数就好了。
    因为那些随意选择的数码已经被计入答案了,所以这么做是对的。
    于是根据乘法原理,还有:
    $$dp[i][j][j]+=10^{i-1}$$
    之后就是数位$DP$的板子了。
    注意:$slove(x)$求的是$[0,x)$满足条件的数的个数!
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAXN 15
    using namespace std;
    int bit[MAXN];
    long long A,B;
    long long ans[MAXN][2],dp[MAXN][MAXN][MAXN];
    inline long long read(){
    	long long date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    long long mexp(long long a,long long b){
    	long long s=1;
    	while(b){
    		if(b&1)s*=a;
    		a*=a;
    		b>>=1;
    	}
    	return s;
    }
    void solve(long long n,int d){
    	int len=0;
    	memset(dp,0,sizeof(dp));
    	memset(bit,0,sizeof(bit));
    	while(n){
    		bit[++len]=n%10;
    		n/=10;
    	}
    	for(int i=0;i<=9;i++)dp[1][i][i]=1;
    	for(int i=2;i<=len;i++)
    	for(int j=0;j<=9;j++){
    		for(int k=0;k<=9;k++)
    			for(int now=0;now<=9;now++)
    				dp[i][j][now]+=dp[i-1][k][now];
    		dp[i][j][j]+=mexp(10,i-1);
    	}
    	for(int i=1;i<len;i++)
    		for(int j=1;j<=9;j++)
    			for(int k=0;k<=9;k++)
    				ans[k][d]+=dp[i][j][k];
    	for(int i=1;i<bit[len];i++)
    		for(int j=0;j<=9;j++)
    			ans[j][d]+=dp[len][i][j];
    	for(int i=len-1;i>=1;i--){
    		for(int j=0;j<bit[i];j++)
    			for(int k=0;k<=9;k++)
    				ans[k][d]+=dp[i][j][k];
    		for(int j=len;j>i;j--)ans[bit[j]][d]+=1LL*bit[i]*mexp(10,i-1);
    	}
    }
    void work(){
    	A=read();B=read();
    	solve(B+1,0);solve(A,1);
    	for(int i=0;i<=9;i++)printf("%lld ",ans[i][0]-ans[i][1]);
    	printf("
    ");
    }
    int main(){
    	work();
        return 0;
    }
    
     
  • 相关阅读:
    学习:组件生命周期(2)
    学习:组件生命周期(3)
    学习:深入分析布局文件(HelloWorld)
    wap webapp app区别
    TCP的数据传输
    SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 详解
    未能加载文件或程序集“SqlServerDal”或它的某一个依赖项。系统找不到指定的文件。
    人生的十个不要等
    asp.net网站三层架构详解和反射知识
    工厂模式概况
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9763787.html
Copyright © 2011-2022 走看看