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

    题意

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

    输入 
    1 99
    输出 
    9 20 20 20 20 20 20 20 20 20
    

    算法

    最近好像喜欢上数位DP了
    这是一个三维的DP
    (dp[i][j][k]) 设从后往前填到第(i)位 这一位上的数字是(j) (k)这个数字出现的次数

    初始化代码

    void init(){
    	for(ll i = 0;i <= 9;i++)
    	dp[1][i][i] = 1;	
    	for(ll i = 2;i <= 12;i++)//第几位
    	for(ll now = 0;now <= 9;now++){//当前的数字
    	dp[i][now][now] = pow(10,i - 1);//先计算现在填的这位的贡献
    	for(ll k = 0;k <= 9;k++)//上一位的数字		
    	for(ll j = 0;j <= 9;j++)//数字
    	dp[i][now][j] += dp[i - 1][k][j];
    	}
    }
    

    我比较习惯在数位DP的时候把DP值求出来 然后根据要求的数字来求解
    对于指定的数字求出答案的细节看下面的代码

    代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define ll long long
    
    using namespace std;
    
    ll dp[13][10][10],ans[10],tans[10],a[13],an,bn;
    
    void init(){
    	for(ll i = 0;i <= 9;i++)
    	dp[1][i][i] = 1;	
    	for(ll i = 2;i <= 12;i++)
    	for(ll now = 0;now <= 9;now++){
    	dp[i][now][now] = pow(10,i - 1);
    	for(ll k = 0;k <= 9;k++)		
    	for(ll j = 0;j <= 9;j++)
    	dp[i][now][j] += dp[i - 1][k][j];
    	}
    }
    
    void solve(ll x){
    	ll cnt = 0;
    	while(x){
    		a[++ cnt] = x % 10;
    		x = x / 10;
    	}//惯用分解数字
    	memset(ans,0,sizeof(ans)); 
    	for(ll i = 1;i < cnt;i++){//先统计位数比x少的数
    		for(ll j = 1;j <= 9;j++)
    			for(ll k = 0;k <= 9;k++)
    			ans[k] += dp[i][j][k];
    	}
    	for(ll i = 1;i < a[cnt];i++)//位数同x一样但是最高位比x最高位小的
    	for(ll k = 0;k <= 9;k++)
    	ans[k] += dp[cnt][i][k];
    	for(ll i = cnt - 1;i >= 1;i--){//位数同x一样最高位也和x一样的
    	for(ll j = 0;j < a[i];j++)
    	for(ll k = 0;k <= 9;k++)
    	ans[k] += dp[i][j][k];
    	for(ll p = cnt;p > i;p--)
    	ans[a[p]] += a[i] * pow(10,i - 1);
    	}
    	return ;
    }
    
    int main(){
    	scanf("%lld%lld",&an,&bn);
    	init();
    	solve(bn + 1);//solve这个函数求的是[0,x)的答案
    	for(ll i = 0;i <= 9;i++)
            tans[i] += ans[i];
            solve(an);
            for(ll i = 0;i <= 9;i++)
            tans[i] -= ans[i];
            for(ll i = 0;i <= 9;i++)
            cout<<tans[i]<<" ";
            return 0;
    }
    
    
  • 相关阅读:
    三范式
    解决Linux下乱码
    ER概念模型
    20140607
    PHP Fatal error: Class 'Yaf_Application' not found
    PHP流式读取XML文件
    php反射的使用
    wget 和curl 进行post数据
    crontab
    Leetcode OJ: Gray Code
  • 原文地址:https://www.cnblogs.com/dixiao/p/13810974.html
Copyright © 2011-2022 走看看