您的位置:首页 > 其它

bzoj1833[ZJOI2010]count 数字计数 数位DP

2017-11-10 12:33 369 查看
题意:求l,r中0-9各个数字的出现次数。

好像是数位DP经典题。。设f[i][j][k]表示做到第i位,当前计算数字j,前i-1位已经出现的次数为k的总出现次数。直接记忆化搜索即可,注意一下前导0.

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
typedef long long ll;
int dig
;
ll f[50][50][50];
inline ll dfs(int x,int num,ll sum,bool tou,bool lim)
{
if (!x)return sum;
if (!lim&&!tou&&f[x][num][sum]!=-1)
return f[x][num][sum];
int n=lim?dig[x]:9;
ll ans=0;
if (!tou||x==1)ans+=dfs(x-1,num,sum+(num==0),0,lim&&dig[x]==0);
else ans+=dfs(x-1,num,sum,1,lim&&dig[x]==0);

fo(i,1,n)
ans+=dfs(x-1,num,sum+(num==i),0,lim&&dig[x]==i);
if (!lim&&!tou)f[x][num][sum]=ans;
return ans;
}
ll solve(ll x,int num)
{
if (x<0)return 0;
if (!x)return num==0?1:0;
int t=0;
while(x)
{
dig[++t]=x%10;
x/=10;
}
return dfs(t,num,0,1,1);
}
int main()
{
int cas;
memset(f,-1,sizeof(f));
ll x,y;
scanf("%lld%lld",&x,&y);
fo(i,0,8)
printf("%lld ",solve(y,i)-solve(x-1,i));
printf("%lld\n",solve(y,9)-solve(x-1,9));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: