薇小薇

”喵喵喵?“

[BZOJ1833][ZJOI2010]数字计数(数位dp)

题目:

我是超链接

题解:

感觉一直不会这类dp
f[i][j][k]表示i位数以j开头,k数字出现的次数

代码:

#include <cstdio> 
#include <cstring>
#define LL long long
using namespace std;
struct hh
{
    LL a[10];
    void clear(){memset(a,0,sizeof(a));}
}f[15][10];
LL t[15];int digit[15];
hh operator +(hh a,hh b)
{
    hh c;
    for (int i=0;i<=9;i++) c.a[i]=a.a[i]+b.a[i];
    return c;
}
hh work(LL a)
{
    int cnt=0;LL wh=a;
    while (wh) digit[++cnt]=wh%10,wh/=10;
    hh c;c.clear();
    c.a[0]=1;
    if (a==0) return c;
    for (int i=1;i<cnt;i++)//最高位为0 
      for (int j=1;j<=9;j++) c=c+f[i][j];

    for (int i=1;i<digit[cnt];i++) c=c+f[cnt][i];//最高位不为0 
    a%=t[cnt]; c.a[digit[cnt]]+=a+1;//最高位不为0紧贴上界 
    for (int i=cnt-1;i>=1;i--)
    {
        for (int j=0;j<digit[i];j++)
          c=c+f[i][j];
        a%=t[i];
        c.a[digit[i]]+=a+1;
    }
    return c;
}
int main()
{
    t[1]=1; for (int i=2;i<=12;i++) t[i]=t[i-1]*10;
    for (int i=0;i<=9;i++) f[1][i].a[i]=1;
    for (int i=2;i<=12;i++)
      for (int j=0;j<=9;j++)
        for (int k=0;k<=9;k++)
        {
            f[i][j]=f[i][j]+f[i-1][k];
            f[i][j].a[j]+=t[i-1];
        }
    LL a,b;
    scanf("%lld%lld",&a,&b);
    hh t1=work(a-1);
    hh t2=work(b);
    for (int i=0;i<=9;i++)
      printf("%lld ",t2.a[i]-t1.a[i]); 
}
阅读更多
版权声明:口胡文章,请谨慎转载╮(╯▽╰)╭ https://blog.csdn.net/Blue_CuSO4/article/details/79970536
文章标签: 数位dp
个人分类: dp 省选
上一篇【loli的胡策】测试4.16(线段树+概率期望dp)
下一篇[BZOJ2425][HAOI2010]计数(数位+组合数学)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭