1. 程式人生 > >P2602 [ZJOI2010]數字計數

P2602 [ZJOI2010]數字計數

-- copy register limit efi ont include fine long long

題目描述

給定兩個正整數a和b,求在[a,b]中的所有整數中,每個數碼(digit)各出現了多少次。

輸入輸出格式

輸入格式:

輸入文件中僅包含一行兩個整數a、b,含義如上所述。

輸出格式:

輸出文件中包含一行10個整數,分別表示0-9在[a,b]中出現了多少次。

輸入輸出樣例

輸入樣例#1:
1 99
輸出樣例#1:
9 20 20 20 20 20 20 20 20 20

說明

30%的數據中,a<=b<=10^6;

100%的數據中,a<=b<=10^12。

Solution:

  本題數位DP板子題

  常規套路,對於每個數碼的情況,處理的方法都是相同的,所以我們可以枚舉當前求的數碼,並定義狀態$f[i][j]$表示到了第$i$位有$j$個當前數碼時往後會出現當前數碼的個數。

  轉移就常規枚舉當前位的值,然後統計個數咯,由於本題不能有前導零,稍微處理下限制條件就ok了。

代碼:

/*Code by 520 -- 9.16*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace
std; int num[15],top,dig; ll n,m,f[15][15]; ll dfs(int pos,int lead,int limit,ll sum){ if(!pos) return sum; if(!limit&&lead&&f[pos][sum]!=-1) return f[pos][sum]; ll tp=0; For(i,0,limit?num[pos]:9) tp+=dfs(pos-1,i||lead,i==num[pos]&&limit,sum+((i||lead)&&(i==dig)));
if(!limit&&lead) f[pos][sum]=tp; return tp; } il ll solve(ll x){ memset(f,-1,sizeof(f)); top=0; while(x) num[++top]=x%10,x/=10; return dfs(top,0,1,0); } int main(){ cin>>n>>m; while(dig<10) cout<<solve(m)-solve(n-1)<< ,dig++; return 0; }

P2602 [ZJOI2010]數字計數