[ZJOI2010] 數字計數
阿新 • • 發佈:2018-09-03
超過 二維 != 多少 uri 輸入輸出格式 get etc solution
f表示當前前導0的條件合不合法,初始值是有前導0的,不合法,所以為0
limit表示當前搜索的這一位有沒有限制,即不能超過原數這一數位上的數字,1表示有限制,0表示沒有
sum表示有多少當前已經統計了多少查找的數字
tq表示當前查找的數字是什麽
題目描述
給定兩個正整數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
bzoj1883
數位dp,記憶化搜索
主要就是解釋一下變量
len指當前搜到哪一位,當len=0時,就返回當前搜到的值
limit表示當前搜索的這一位有沒有限制,即不能超過原數這一數位上的數字,1表示有限制,0表示沒有
sum表示有多少當前已經統計了多少查找的數字
tq表示當前查找的數字是什麽
本來正常情況下,dp數組是要開四維的,\(dp[len][f][limit][sum]\),但是由於本題只在沒有前導0以及當前位所有數字都搜滿的情況下也就是(\(f\) && \(!limit\)),所以可以省去這兩維
提示:關於數組大小,因為我們統計的數字做多只有15位,所以第1維開16即可,第二維因為每次只統計一個數字x,所以最好情況下就是每一位都是x,最多也就是15位,所以也只要開16
Code
#define lol long long #define Min(a,b) (a)<(b)?(a):(b) #define Max(a,b) (a)>(b)?(a):(b) using namespace std; const int N=20; lol dp[N][N]; int bit[N]; void in(lol &ans) { ans=0;lol f=1; char i=getchar(); while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();} while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar(); ans*=f; } lol dfs(int len,int f,int limit,lol sum,int tq,lol ans=0) { if(!len) return sum; if(!limit && f && dp[len][sum]!=-1) return dp[len][sum]; int maxn=limit?bit[len]:9; for(int i=0;i<=maxn;i++) ans+=dfs(len-1,f||i,limit && i==maxn,sum+((f||i) && (i==tq)),tq); if(!limit && f) dp[len][sum]=ans; return ans; } lol solve(lol a,int tq,int k=0) { memset(dp,-1,sizeof(dp)); while(a) { bit[++k]=a%10; a/=10; } return dfs(k,0,1,0,tq); } int main() { lol a,b; in(a),in(b); for(int i=0;i<10;i++) printf("%lld ",solve(b,i)-solve(a-1,i)); puts(""); return 0; }
博主蒟蒻,隨意轉載.但必須附上原文鏈接
http://www.cnblogs.com/real-l/
[ZJOI2010] 數字計數