您的位置:首页 > 其它

BZOJ 1833 count 数字计数 (数位DP)

2017-08-04 15:42 337 查看
给定两个正整数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。

Emmmmm…………

说实话这个题我是怎么过的我都不知道………………

一共十个数字0,1,2,3,4,5,6,7,8,9,不可能一下子全部算出来,还是先算0再算1这样子遍历每一个数字分开计算

dp[ i ] 表示第 i 位为止的数后面出现了多少个 0 ( or 1,2 ..........9  )

然后就瞎搞

其实这个题对于每一个数码找它出现的次数的思路应该还是蛮清晰的吧。。。。。。

代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
#define fi first
#define se second
LL dp[20],s[20],t[20];
LL n[20];
LL a,b,m;
LL dfs(LL pos,LL sum,LL num,bool limit)
{
if(pos==-1)
{
if(sum==0&&num==0&&m==0)return 1;
else return 0;
}
if(!limit&&sum>0&&dp[pos]>-1)return dp[pos];
LL up=limit?n[pos]:9;
LL res=0;
for(int i=0;i<=up;i++)
{
LL z=(sum*10+i>0)&&(i==m);
if(limit&&i==up)
{
res+=z*(pos>0?(s[pos-1]+1):1)+dfs(pos-1,sum*10+i,i,true);
}
else
{
res+=z*t[pos]+dfs(pos-1,sum*10+i,i,false);
}
}
if(!limit&&sum>0)dp[pos]=res;
return res;
}

LL solve(LL x)
{
LL len=0;
while(x)n[len++]=x%10,x/=10;
s[0]=n[0];t[0]=1;
LL z=10;
for(int i=1;i<len;i++)s[i]=s[i-1]+n[i]*z,t[i]=z,z*=10;
//for(int i=0;i<len;i++)cout<<s[i]<<' ';puts("");
return dfs(len-1,0,0,true);
}

int main()
{
while(scanf("%lld%lld",&a,&b)!=-1)
{
a--;
for(m=0;m<=9;m++)
{
memset(dp,-1,sizeof(dp));
printf("%lld",solve(b)-solve(a));
if(m<9)putchar(' ');else putchar('\n');
}
}
return 0;
}
大概就是这样了。。。。。

本人蒟蒻,如有错误,还望指正

(虽然今天是8月4号晚了一天的但还是要说果果生日快乐)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: