您的位置:首页 > 其它

Bzoj1833:[ZJOI2010]count 数字计数:数位dp

2016-04-19 16:17 465 查看
题目链接[ZJOI2010]count 数字计数

设f[i][j][k]表示长度为i,开头为j的数中k的个数

分开统计答案,对于位数小于当前数的直接全部加上,剩余的拆分统计

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=51;
LL a,b,ret[maxn],f[maxn][maxn][maxn],bin[maxn];
int d[maxn];

LL solve(LL x,int flag){
int dnum=0; LL tmpn=x;
memset(d,0,sizeof(d));
while(x){d[++dnum]=x%10;x/=10;}
for (int i=1;i<=dnum-1;++i)
for (int j=1;j<=9;++j)
for (int k=0;k<=9;++k)
ret[k]+=(f[i][j][k]*flag);
int tmp=dnum;
while (tmp){
for (int i=0;i<d[tmp];++i){
if (!i&&tmp==dnum) continue;
for (int j=0;j<=9;++j)
ret[j]+=(f[tmp][i][j]*flag);
}
ret[d[tmp]]+=(tmpn%bin[tmp]+1)*flag;
tmp--;
}
}

int main(){
bin[1]=1;
for (int i=2;i<=13;++i) bin[i]=bin[i-1]*10;
for (int i=0;i<=9;++i) f[1][i][i]=1;
for (int i=2;i<=13;++i)
for (int j=0;j<=9;++j)
for (int k=0;k<=9;++k){
for (int z=0;z<=9;++z)
f[i][j][z]+=f[i-1][k][z];
f[i][k][k]+=bin[i-1];
}
scanf("%lld%lld",&a,&b);
solve(b,1); solve(a-1,-1);
for (int i=0;i<=8;++i) printf("%lld ",ret[i]);
printf("%lld\n",ret[9]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BZOJ OI 数位dp