【bzoj 1833】【codevs 1359】 [ZJOI2010]count 数字计数(数位dp)

来源:互联网 发布:js数组去重 es6 编辑:程序博客网 时间:2024/05/16 17:22

1833: [ZJOI2010]count 数字计数

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 2774  Solved: 1230
[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

[Submit][Status][Discuss]

【题解】【数位dp】

[自己乱搞的结果就是写了三遍。。。每一遍想法都有所改变……蠢哭]

【刚开始想的是用f[i][j][k][o][x][y]表示第i位放j时k的出现次数,o表示前导0,x,y表示是否到达左右边界,每次下一位与当前位的相同时,更新时就加1,然后,怎么搞都错成一团。。。扔掉!】

【然后,又考虑用f[i][j][k][o][x][y]表示第i位放j时j出现的次数k,o表示前导0,x,y表示是否到达左右边界,每一次都是加上更新过来的f[i][j][k][o][x][y],然后,发现怎么搞1都不对。。。又扔掉!】

【最后,结合前两次的经验,先循环一重当前要求数t的出现次数,用f[i][j][k][o][x][y]表示第i位放j时t的出现次数k,o表示前导0,x,y表示是否到达左右边界。循环9次,卡过了。。。】

【注意,这种方法,由于要判断前导0,把零先去掉了,如果区间中包含0的话,要特判】

#include<cstdio>#include<cstring>#include<algorithm>#define ll long longusing namespace std;ll a,b,ans;int al[15],ar[15],left[15],right[15],l,r,len;int f[15][12][15][3][3][3];int main(){freopen("int.txt","r",stdin);freopen("my.txt","w",stdout);int i,j,k,xx;scanf("%lld%lld",&a,&b); xx=a;while(a) left[++l]=a%10,a/=10;while(b) right[++r]=b%10,b/=10;len=max(l,r);memset(f,0,sizeof(f));for(i=1;i<=len;++i) al[len-i+1]=left[i],ar[len-i+1]=right[i];for(int t=0;t<=9;++t) { memset(f,0,sizeof(f));for(i=al[1];i<=ar[1];++i) f[1][i][i==t&&i!=0][i==0][i==al[1]][i==ar[1]]=1; for(i=1;i<len;++i)  for(j=0;j<=9;++j)   for(k=0;k<=12;++k)    for(int o=0;o<=1;++o)     for(int x=0;x<=1;++x)      for(int y=0;y<=1;++y)       if(f[i][j][k][o][x][y])        {            if(x&&y)             {             for(int h=al[i+1];h<=ar[i+1];++h)              {              int p;              if(h||!o) p=k+(t==h),f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];                else p=0,f[i+1][h][0][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];    }    continue;     }     if(!x&&!y)     {     for(int h=0;h<=9;++h)      {              int p;              if(h||!o) p=k+(t==h),f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];                else p=0,f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];             }    continue; }if(!x) { for(int h=0;h<=ar[i+1];++h)  {              int p;              if(h||!o) p=k+(t==h),f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];                else p=0,f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];    }    continue; }if(!y) { for(int h=al[i+1];h<=9;++h)  {              int p;              if(h||!o) p=k+(t==h),f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];                else p=0,f[i+1][h][p][o&(h==0)][x&(h==al[i+1])][y&(h==ar[i+1])]+=f[i][j][k][o][x][y];    }    continue; }}ans=0;for(i=0;i<=9;++i) for(j=1;j<=12;++j)  for(k=0;k<=1;++k)   ans+=(ll)(f[len][i][j][k][1][1]+f[len][i][j][k][1][0]+f[len][i][j][k][0][1]+f[len][i][j][k][0][0])*j;if(!t&&!xx) printf("%lld ",ans+1); else printf("%lld ",ans);if(t==9) printf("\n"); }return 0;}


0 0
原创粉丝点击