• P2602 [ZJOI2010]数字计数


    (color{#0066ff}{ 题目描述 })

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

    (color{#0066ff}{输入格式})

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

    (color{#0066ff}{输出格式})

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

    (color{#0066ff}{输入样例})

    1 99
    

    (color{#0066ff}{输出样例})

    9 20 20 20 20 20 20 20 20 20
    

    (color{#0066ff}{数据范围与提示})

    30%的数据中,(aleq bleq 10^6)

    100%的数据中,(aleq bleq 10^{12})

    (color{#0066ff}{ 题解 })

    一道基本的数位DP

    本来以前做过的,代码太不清真了qwq,改一下

    (f[i][j][k])为长度为i,最高位为j,k出现的次数

    #include<bits/stdc++.h>
    using LL = long long;
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    LL f[25][10][10], base[16];
    LL ans1[10], ans2[10];
    LL l, r, a[20], num, b[20];
    void init() {
    	base[0] = 1;
    	for(int i = 1; i <= 13; i++) { 
    		base[i] = base[i - 1] * 10; 
    		for(int j = 0; j <= 9; j++) 
    			for(int k = 0; k <= 9; k++) {
    				for(int l = 0; l <= 9; l++)
    					f[i][j][l] += f[i - 1][k][l];
    				if(j == k) f[i][j][j] += base[i - 1]; //最高位不动,后面随意的贡献
    			}
    
    		}
    }
    void query(LL p, LL *ans) {
    	num = 0;
    	while(p) {
    		a[++num] = p % 10;
    		b[num] = b[num - 1] + base[num - 1] * (p % 10);  //从num位开始的数
    		p /= 10;
    	}
    	for(int i = 1; i < num; i++)
    		for(int j = 1; j <= 9; j++)
    			for(int k = 0; k <= 9; k++)
    				ans[k] += f[i][j][k];   //不贴边的
    	for(int i = 1; i < a[num]; i++)      //无前导零的贴边
    		for(int j = 0; j <= 9; j++)
    			ans[j] += f[num][i][j];
    	ans[a[num]] += b[num - 1];      //作为某一位的贡献(后面什么数,最高位不变,统计贡献)
    	for(int i = num - 1; i >= 1; i--) {
    		for(int j = 0; j < a[i]; j++)
    			for(int k = 0; k <= 9; k++)  //贴边统计
    				ans[k] += f[i][j][k];
    		ans[a[i]] += b[i - 1]; 
    	}
    }
    
    int main() {
    	init();
    	l = in(), r = in();
    	query(l, ans1);
    	query(r + 1, ans2);
    	for(int i = 0; i <= 9; i++) printf("%lld%c", ans2[i] - ans1[i] , i == 9? '
    ' : ' ');
    	return 0;
    }
    
  • 相关阅读:
    【转载】Linux 内核启动时间分析
    hackbench
    c用户组函数
    c环境变量操作函数
    c网络接口套接字函数
    c信号处理函数
    c进程操作函数
    c文件内容操作函数
    c文件操作
    c数据结构和算法
  • 原文地址:https://www.cnblogs.com/olinr/p/10242375.html
Copyright © 2020-2023  润新知