题目描述
题解
首先枚举要计算个数的数字x
f(i,j,k,0/1,0/1,0/1)表示前i位,第i位填数字j,是x的数字有k个,是否卡下界L,是否卡上界R,1~i位是否都是前导0的数字个数。
那么答案即为f(n,j,k,0/1,0/1,0)*k
注意转移的时候要分别处理是前导0和不是前导0的情况。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
int n;
int a[20],b[20];
LL L,R,f[20][20][20][2][2][2],ans;
int main()
{
scanf("%lld%lld",&L,&R);
while (L)
{
a[++a[0]]=L%10;
L/=10;
}
while (R)
{
b[++b[0]]=R%10;
R/=10;
}
n=max(a[0],b[0]);
for (int i=1;i<=n/2;++i) swap(a[i],a[n-i+1]);
for (int i=1;i<=n/2;++i) swap(b[i],b[n-i+1]);
for (int x=0;x<=9;++x)
{
memset(f,0,sizeof(f));
for (int i=a[1];i<=b[1];++i) f[1][i][i==x&&x!=0?1:0][i==a[1]?1:0][i==b[1]?1:0][i==0?1:0]=1;
for (int i=1;i<n;++i)
for (int j=0;j<=9;++j)
for (int k=0;k<=n;++k)
for (int c=0;c<=1;++c)
for (int d=0;d<=1;++d)
for (int e=0;e<=1;++e)
{
int l,r;
if (c&&d) l=a[i+1],r=b[i+1];
else if (!c&&!d) l=0,r=9;
else if (!c) l=0,r=b[i+1];
else if (!d) l=a[i+1],r=9;
for (int t=l;t<=r;++t)
{
if (!e)
f[i+1][t][t==x?k+1:k][c&(t==a[i+1]?1:0)][d&(t==b[i+1]?1:0)][0]+=
f[i][j][k][c][d][e];
else
f[i+1][t][t==0?0:(t==x?1:0)][c&(t==a[i+1]?1:0)][d&(t==b[i+1]?1:0)][e&(t==0)?1:0]+=
f[i][j][k][c][d][e];
}
}
ans=0;
for (int j=0;j<=9;++j)
for (int k=1;k<=n;++k)
for (int c=0;c<=1;++c)
for (int d=0;d<=1;++d)
ans+=f[n][j][k][c][d][0]*(LL)k;
printf("%lld%c",ans," \n"[x==9]);
}
}
总结
①写这个要细心。每一个状态一定要表示得精确。