1833: [ZJOI2010]count 数字计数
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 2759 Solved: 1221
[ 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
HOME Back
题解:数位dp
枚举t=0..9
f[i][j][k][0/1][0/1][0/1] 表示第I为填数字j,1-i位中t出现的次数为k,是否卡上限,是否卡下限,是否1-i位为前导零。
最后统计ans+=f[cnt][j][k][0/1][0/1][0/1]*k
注意特判0的情况,不是前导零才计算。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 20
#define LL long long
using namespace std;
LL n,m,a1[N],b1[N],f[N][N][N][3][3][3],cnt,ans,num[N],size[N],g[N][N][N][3][3][3];
int main()
{
scanf("%lld%lld",&n,&m);
cnt=0;
while (m)
{
a1[++cnt]=m%10;
m/=10;
}
for (int i=cnt;i>=1;i--)
b1[cnt-i+1]=a1[i],a1[i]=0;
size[0]=1;
for (int i=1;i<=cnt;i++)
size[i]=size[i-1]*10;
int t=0;
while (n)
{
t++;
a1[cnt-t+1]=n%10;
n/=10;
}
for (int t=0;t<=9;t++)
{
memset(f,0,sizeof(f));
for (int i=a1[1];i<=b1[1];i++)
f[1][i][i==t&&t!=0?1:0][i==a1[1]?1:0][i==b1[1]?1:0][i==0?1:0]=1;
for (int i=1;i<=cnt-1;i++)
for (int j=0;j<=9;j++)
for (int l=0;l<=12;l++)
for (int a=0;a<=1;a++)
for (int b=0;b<=1;b++)
for (int c=0;c<=1;c++)
if (f[i][j][a][b][c])
{
if (a&&b)
for(int k=a1[i+1];k<=b1[i+1];k++)
if (!c||k!=0)
f[i+1][k][l+(k==t?1:0)][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else f[i+1][k][0][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else
if (!a&&!b)
for (int k=0;k<=9;k++)
if (!c||k!=0)
f[i+1][k][l+(k==t?1:0)][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else f[i+1][k][0][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else
if (!a)
for (int k=0;k<=b1[i+1];k++)
if (!c||k!=0)
f[i+1][k][l+(k==t?1:0)][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else f[i+1][k][0][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else
if (!b)
for (int k=a1[i+1];k<=9;k++)
if (!c||k!=0)
f[i+1][k][l+(k==t?1:0)][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
else f[i+1][k][0][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][l][a][b][c];
}
ans=0;
for (int i=0;i<=9;i++)
for (int j=1;j<=12;j++)
for (int a=0;a<=1;a++)
for (int b=0;b<=1;b++)
for (int c=0;c<=1;c++)
ans+=f[cnt][i][j][a][b][c]*(LL)j;
if (t!=9) printf("%lld ",ans);
else printf("%lld\n",ans);
}
}