zoukankan      html  css  js  c++  java
  • BZOJ1833 [ZJOI2010]count 数字计数 【数学 Or 数位dp】

    题目

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

    输入格式

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

    输出格式

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

    输入样例

    1 99
    

    输出样例

    9 20 20 20 20 20 20 20 20 20
    

    提示

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

    题解

    你以为我真的会写数位dp?

    首先容斥一下,转化为求小于等于n的方案数

    如果不考虑前缀0,那么就只需要递归处理不大于n所有数字出现的次数
    考虑前缀0,我们再减去开头有若干个0的方案数

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 15,maxm = 100005,INF = 1000000000;
    LL g[maxn],Pow[maxn];
    void init(){
    	Pow[0] = 1;
    	for (int i = 1; i < maxn; i++) Pow[i] = Pow[i - 1] * 10;
    	g[1] = 1;
    	for (int i = 2; i < maxn; i++){
    		g[i] = 10 * g[i - 1] + Pow[i - 1];
    	}
    }
    struct node{
    	LL t[10];
    	node(){memset(t,0,sizeof(t));}
    };
    node cal(LL n,LL h,LL tmp){
    	//cout << n << endl;
    	node re,t;
    	if (h == 1){
    		for (int i = 0; i <= n; i++) re.t[i] = 1;
    		return re;
    	}
    	for (int i = 0; i <= 9; i++){
    		re.t[i] += (n / tmp) * g[h - 1];
    		if (i < n / tmp) re.t[i] += Pow[h - 1];
    	}
    	re.t[n / tmp] += n - (n / tmp) * tmp + 1;
    	t = cal(n % tmp,h - 1,tmp / 10);
    	for (int i = 0; i <= 9; i++) re.t[i] += t.t[i];
    	return re;
    }
    node solve(LL n){
    	LL h = 1,tmp = 1;
    	for (LL i = n; i / 10; i /= 10) h++,tmp *= 10;
    	node re = cal(n,h,tmp);
    	for (int i = 1; i < h; i++){
    		re.t[0] -= Pow[h - i];
    	}
    	return re;
    }
    int main(){
    	init();
    	LL a,b;
    	cin >> a >> b;
    	node ansr = solve(b),ansl = solve(a - 1);
    	for (int i = 0; i < 9; i++) printf("%lld ",ansr.t[i] - ansl.t[i]);
    	printf("%lld",ansr.t[9] - ansl.t[9]);
    	return 0;
    }
    
    
  • 相关阅读:
    java中的重绘
    引起共鸣的句子【转自知乎】
    东大校园网一键登录
    java用字符写字符
    Xshell 配置上传下载命令 rz sz 以及配置复制和粘贴
    【测试工程师面试】 记录XX银行面试
    常见的加密解密算法
    SHA-256 加密原理
    Spring boot 整合JSP开发步骤
    Spring boot @Scheduled(cron = "* * * * * *") cron表达式详解
  • 原文地址:https://www.cnblogs.com/Mychael/p/8733863.html
Copyright © 2011-2022 走看看