P2602 [ZJOI2010]數字計數
阿新 • • 發佈:2018-09-17
-- 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 namespacestd; 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]數字計數