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

    偷得题面

    设f[i]代表第i位上不算前导零每个数出现多少次

    比如54321

    首先是5,,5在万位上,那么个十百千位每个数都会出现至少5*f[bit]次,然后万位上,5以下的数都会出现,然后以此类推

    最后加完所有位之后,在处理4321这样的跑不满的零位就好了qwq

    代码

    DFS版

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <queue>
    #define int long long
    using namespace std ;
    int read() {
    	int x = 0 , f = 1 ; char s = getchar() ;
    	while(s > '9' || s < '0') {if(s == '-') f = -1 ; s = getchar() ;}
    	while(s <='9' && s >='0') {x = x * 10 + (s-'0'); s = getchar() ;}
    	return x*f ;
    }
    int l , r ;
    int f[15][15] , num[15]  ;
    int dfs(int pos,int sum ,int lead ,int limit,int d) {
    	if(!pos) return sum ;
    	if(!limit&&f[pos][sum]!=-1&&!lead) return f[pos][sum] ;
    	int up = limit? num[pos] : 9 ;
    	int ans = 0 ;
    	for(int i = 0 ; i <= up ; i ++) {
    		ans += dfs(pos-1,sum+((i||!lead)&&(i==d)),lead&&(i==0) , limit && (i == num[pos]),d) ;
     	}
     	if(!lead && !limit) f[pos][sum] = ans ;
     	return ans ;
    }
    int calc(int x,int d) {
    	int len = 0 ;
    	while(x) {
    		num[++len] = x % 10 ;
    		x /= 10 ;
    	}
    	memset(f,-1,sizeof f) ;
    	return dfs(len,0,1,1,d) ;
    }
    signed main () {
    	l = read() , r = read() ;
    	for(int i = 0 ; i < 10 ; i ++) {
    		cout << calc(r,i) - calc(l-1,i) << " " ;
    	}
    	return 0 ;
    }
    

    循环

    #include <bits/stdc++.h>
    #define int long long
    using namespace std ;
    int a , b ;
    int ten[15] , f[15] ;
    int cnta[15] , cntb[15] , num[10] ;
    void work(int x ,int cnt[])  {
    	for(int i = 0 ; i < 10 ; i ++) num[i] = 0 ;
    	int len = 0 ;
    	while(x) {//拆数 
    		num[++len] = x%10 ;
    		x = x / 10 ; 
    	}
    	for(int i = len ; i >= 1 ; i --) {
    		for(int j = 0 ; j <= 9 ; j ++) {
    			cnt[j] += f[i-1] * num[i] ; //第i位之后的每位每个数数都会出现i次 
    		}
    		for(int j = 0 ; j < num[i] ; j ++) {
    			cnt[j] += ten[i-1] ;//第i位是x,那么在x之前的都会在出现10^(bit-1)次 
    		}
    		//--------以上只是处理A000000....00这亚子----------//
    		//--------以下处理零位--------// 
    		int num2 = 0 ;
    		for(int j = i-1 ; j >= 1 ; j --) {
    			num2 = num2 * 10 + num[j] ;//加上零位 
    		}
    		cnt[num[i]] += num2 + 1 ;// num2是零位,1是最高位
    		cnt[0] -= ten[i-1] ;//清除前导零 
    	}
    }  
    signed main () {
    	scanf("%lld%lld",&a,&b) ;
    	ten[0] = 1 ;//10的阶乘,每一位代表多少 
    	for(int i = 1 ; i <= 15 ; i ++) {
    		f[i] = f[i-1] * 10 + ten[i-1] ;//在第i位有数字的时候,每个数码有多少个 
    		ten[i] = 10*ten[i-1] ; 
    	}
    	work(a-1,cnta) ;//work(0-x的各数位,统计答案的数组) 
    	work(b,cntb) ;
    	for(int i = 0 ; i <= 9 ; i ++) printf("%lld ",cntb[i] - cnta[i]) ;
    	return 0 ;
    } 
    

    举个栗子: 32345

    首先 是 5f[0] ,然后4f[1] (也就是4个一位数所有的数,因此当前位数4是没有算上的),然后是3*f[2] (也就是4个两位数所有的数,因此当前位数3是没有算上的)....以此类推

    然后我们成功的处理完len-1位(y因为这些位数一定是合法的)后,开始考虑len位,首先,num[len]-1个ten[i-1]次(y因为最后一位不算零头也只能出现这些),然后在填上零头就好了

  • 相关阅读:
    vue-指令
    VueMusic-14搜索实现
    VueMusic-13歌手列表
    VueMusic-12歌词滚动
    VueMusic-11播放-歌词适配
    VueMusic-10.播放-歌词加载
    VueMusic-9.播放-播放功能
    VueMusic-8更多-下拉刷新
    VueMusic-7更多-数据适配
    VueMusic-6首页-热门榜单
  • 原文地址:https://www.cnblogs.com/lyt020321/p/11750513.html
Copyright © 2011-2022 走看看