【BZOJ1833/POJ3252/ZJOI2010】Round Numbers/count 數字計數
阿新 • • 發佈:2018-12-12
1833: [ZJOI2010]count 數字計數
Time Limit: 3 Sec Memory Limit: 64 MB Submit: 4815 Solved: 2212
Description
給定兩個正整數a和b,求在[a,b]中的所有整數中,每個數碼(digit)各出現了多少次。
Input
輸入檔案中僅包含一行兩個整數a、b,含義如上所述。
Output
輸出檔案中包含一行10個整數,分別表示0-9在[a,b]中出現了多少次。
Sample Input
1 99
Sample Output
9 20 20 20 20 20 20 20 20 20
HINT
30%的資料中,a<=b<=10^6; 100%的資料中,a<=b<=10^12。
解析:
數位DP。
注意DP的狀態一定要定義完整,否則涼涼。
程式碼(單組資料,POJ上是多組資料):
#include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #include <cctype> #include <cstring> #define int long long using namespace std; const int Max=14; int l,r,n,m,num[Max],f[Max][Max][2],s1[Max],s2[Max]; inline int dfs(int pos,int id,int sum,int tag,int limit) { if(!pos) return sum; if(!limit&&~f[pos][sum][tag]) return f[pos][sum][tag]; int mx=limit?num[pos]:9,ans=0,now=tag; for(int i=0;i<=mx;++i) { if(i) now=1; if(id) ans+=dfs(pos-1,id,sum+(i==id),now,limit&&(i==mx)); else ans+=dfs(pos-1,id,sum+((i==id)&now),now,limit&&(i==mx)); } if(!limit) return f[pos][sum][tag]=ans; return ans; } inline void solve(int x,int tag) { m=0; while(x)num[++m]=x%10,x/=10; for(int i=0;i<=9;i++) { memset(f,-1,sizeof(f)); if(!tag) s1[i]=dfs(m,i,0,0,1); else s2[i]=dfs(m,i,0,0,1); } } signed main() { cin>>l>>r; solve(r,0),solve(l-1,1); for(int i=0;i<=9;++i) cout<<s1[i]-s2[i]<<" "; cout<<"\n"; return 0; }