您的位置:首页 > 其它

【BZOJ-1833】count数字计数 数位DP

2016-04-29 21:30 417 查看

1833: [ZJOI2010]count 数字计数

Time Limit: 3 Sec Memory Limit: 64 MB
Submit:
2494 Solved: 1101
[Submit][Status][Discuss]

Description

给定两个正整数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。

Source

Day1

Solution

裸的数位DP,但其实并不是特别的水

首先F[i][j][k]表示位数为i的最高位为j的k种数的个数

按照十进制拆分,预处理后统计答案

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long L,R;
long long F[15][10][10],ans1[10],ans2[10];
void prework()
{
for (int i=0; i<=9; i++) F[1][i][i]=1;
long long tmp=1;
for (int i=2; i<=12; i++)
{
tmp*=10;
F[i][0][0]=F[i-1][1][0]*9+F[i-1][0][0]+tmp;
for (int j=1; j<=9; j++)
F[i][0][j]=F[i-1][0][j]*9+F[i-1][j][j];
for (int j=1; j<=9; j++)
{
F[i][j][0]=F[i-1][1][0]*9+F[i-1][0][0];
for (int k=1; k<=9; k++)
if (j==k)
F[i][j][k]=F[i-1][0][k]*9+F[i-1][k][k]+tmp;
else
F[i][j][k]=F[i-1][0][k]*9+F[i-1][k][k];
}
}
}
long long cf(int x)
{
long long re=1;
for (int i=1; i<x; i++)
re*=10;
return re;
}
void Calc(long long x,long long *ans)
{
int digit[15]={0},len=0; long long y=x;
while (x) {digit[++len]=x%10; x/=10;}
for (int i=1; i<len; i++)
for (int j=1; j<=9; j++)
for (int k=0; k<=9; k++)
ans[k]+=F[i][j][k];
for (int i=len; i>=1; i--)
{
for (int j=0; j<=digit[i]-1; j++)
{
if (i==len && j==0) continue;
for (int k=0; k<=9; k++) ans[k]+=F[i][j][k];
}
ans[digit[i]]+=y%cf(i)+1;
}
}
int main()
{
prework();
scanf("%lld%lld",&L,&R);
Calc(L-1,ans1); Calc(R,ans2);
printf("%lld",ans2[0]-ans1[0]);
for (int i=1; i<=9; i++) printf(" %lld",ans2[i]-ans1[i]);
return 0;
}


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