1833: [ZJOI2010]count 数字计数
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 3528 Solved: 1553
[ 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
经典题,数位dp,求0的个数可以最后用数字总数与1-9数字个数相减
#include<stdio.h>
#define LL long long
char str[20];
LL len, dp[10][20], ans1[15], ans2[15];
LL Sech(int x, int t, int flag);
LL Zero(LL c);
LL Jud(LL k, int x);
LL Pow(int k)
{
LL sum = 1;
while(k--)
sum *= 10;
return sum;
}
int main(void)
{
LL a, i, j, b, sum1, sum2;
for(i=1;i<=9;i++)
for(j=0;j<=19;j++)
dp[i][j] = -1;
while(scanf("%lld%lld", &a, &b)!=EOF)
{
sum1 = sum2 = 0;
for(i=1;i<=9;i++)
{
ans1[i] = Jud(b, i), ans2[i] = Jud(a-1, i);
sum1 += ans1[i], sum2 += ans2[i];
}
printf("%lld", Zero(b)-sum1-Zero(a-1)+sum2);
for(i=1;i<=9;i++)
printf(" %lld", ans1[i]-ans2[i]);
printf("\n");
}
return 0;
}
LL Zero(LL c) //统计有多少个数字,那么0的个数就是数字总数-∑数字1-9个个数
{
int len;
if(c==0) return 0;
LL temp = c, sum = 0;
for(len=0;c>0;c/=10)
len++;
sum += (temp-Pow(len-1)+1)*len;
while(--len)
sum += 9*Pow(len-1)*len;
return sum;
}
LL Jud(LL k, int x)
{
int len = 0;
while(k)
{
str[++len] = k%10+'0';
k /= 10;
}
str[len+1] = '\0';
return Sech(x, len, 1);
}
LL Sech(int x, int len, int flag)
{
int u, i, j;
LL k, ans;
if(len==0)
return 0;
if(flag==0 && dp[x][len]!=-1)
return dp[x][len];
u = flag? str[len]-'0':9;
ans = 0;
for(i=0;i<=u;i++)
{
if(i==x)
{
if(flag && i==u)
{
k = 0;
for(j=len-1;j>=1;j--)
k = k*10+str[j]-'0';
ans += ++k;
}
else
ans += Pow(len-1);
}
ans += Sech(x, len-1, flag && i==u);
}
if(flag==0)
dp[x][len] = ans;
return ans;
}