黄月英【题解 义乌中学模拟赛】

LuckyCloud

2018-07-17 19:24:33

Personal

### 题目描述 xpp每天研究天文学研究哲学,对于人生又有一些我们完全无法理解的思考。 在某天无聊学术之后,xpp打开了 http://web.sanguosha.com, 准备用他心爱的黄月英虐人。进入了八人身份局,作为一位主公,xpp果断选了黄月英,用黄月英挑7人。 xpp为什么喜欢黄月英这个武将呢?因为集智是个很牛逼的技能。 集智——每当你使用一张非延时类锦囊(在它结算之前)你可以立即摸一张牌。 可见集智这个技能如果用得好那么牌是摸不完的。于是xpp把7个人全部轻松干掉。 虽然xpp的集智永远都能摸锦囊,但是他想到了这样一个问题:由于黄月英是一个富有智慧的人,所以xpp也要想一个富有智慧的问题,具体说来,他对牌上的数字产生了兴趣,于是他想知道,牌上每个数字出现过多少次。 当然,要算牌上的数字太简单了。所以xpp要扩大范围。 xpp正在考虑这样一个问题:从一个数字a到另一个数字b之间,从0到9的每个数字出现过多少次。 xpp智商过于强大,不屑于想此等低端问题,然后你就要把这道题做出来。 ### 输入输出格式 #### 输入格式: 共一行,每行两个整数,分别为a,b。 #### 输出格式: 输出共一行,包含10个整数,分别代表从0到9的数字各出现过多少次。 ### 输入输出样例 #### 输入样例#1 24 69 #### 输出样例#2 4 4 10 14 15 15 15 5 5 5 ### 解题过程 #### 内心OS 本来自信满满准备来一波自认为很熟悉的数位DP,结果发现自己还是有些没理解,以为能秒掉的QAQ,没想到搞了一下午才过,数位DP真是博大精深啊,顺便提一下dp[x]是从最低位到第x位有多少个0,1,2,3,4,5,6,7,8,9。 #### 丑陋的标程 ```cpp #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long pos,l,r,num[20],t[13]; struct data { long long a[10],sum; bool f; data operator -(const data x) { data ret; for (int i=0;i<10;i++) { a[i]-=x.a[i]; ret.a[i]=a[i]; } return ret; } data operator +(const data x) { data ret; for (int i=0;i<10;i++) { a[i]+=x.a[i]; ret.a[i]=a[i]; } ret.sum=sum+x.sum; return ret; } }dp[20],ans; data dfs(int x,int n,bool limit,bool lead) { data ret;memset(ret.a,0,sizeof(ret.a));ret.sum=0; if (x<=0) { ret.a[n]=1; ret.sum=1; return ret; } if (!limit&&dp[x].f&&!lead) { ret=dp[x]; ret.a[n]+=t[x+1]; return ret; } for (int i=0;i<=num[x]||(limit==false&&i<=9);i++) ret=ret+dfs(x-1,i,limit&&i==num[x],lead&&i==0); if (!limit&&!lead) { dp[x]=ret; dp[x].f=true; } if (!lead) { if (!limit) ret.a[n]+=t[x+1]; else ret.a[n]+=ret.sum; } return ret; } data solve(long long x) { pos=0; data ret;memset(ret.a,0,sizeof(ret.a)); while (x) { num[++pos]=x%10; x/=10; } t[1]=1; for (int i=2;i<=pos;i++) t[i]=t[i-1]*10; for (int i=0;i<=num[pos];i++) ret=ret+dfs(pos-1,i,i==num[pos],i==0); return ret; } inline long long read() { long long cnt=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){cnt=cnt*10+ch-48;ch=getchar();} return cnt*f; } int main() { l=read();r=read(); ans=solve(r)-solve(l-1); for (int i=0;i<=9;i++) printf("%lld ",ans.a[i]); return 0; } ```