bzoj 1833 数字计数|数位dp

又一类数位dp模板,直接贴代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N
using namespace std;
ll mi[20];
struct data { ll a[15];} f[20][15];
data operator + (data a,data b)
{
 data ans;
 memset(ans.a,0,sizeof(ans.a));
 for (int i=0;i<=9;i++) ans.a[i]=a.a[i]+b.a[i];
 return ans;
}

void ycl()
{
 mi[0]=1;
 for (int i=1;i<=13;i++) mi[i]=mi[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]+=mi[i-1];
   }

data dp(ll x)
{
 data ans; memset(ans.a,0,sizeof(ans.a));
 if (x==0) { return ans;}
 int len=13;
 while (mi[len-1]>x) len--; //printf("x: %lld len: %d\n",x,len);
 for (int i=1;i<len;i++)
   for (int j=1;j<=9;j++)
     ans=ans+f[i][j];
 int fir=x/mi[len-1];
 for (int i=1;i<fir;i++) ans=ans+f[len][i];
 x%=mi[len-1]; ans.a[fir]+=x+1;
 for (int i=len-1;i;i--)
 {
  fir=x/mi[i-1];
  for (int j=0;j<fir;j++) ans=ans+f[i][j];
  x%=mi[i-1]; ans.a[fir]+=x+1;
 }
 //ans.a[0]++;
 return ans;
}
int main()
{
 ll a,b;
 ycl();
 scanf("%lld%lld",&a,&b);
 data ans1=dp(a-1),ans2=dp(b);
 printf("%lld",ans2.a[0]-ans1.a[0]);
 for (int i=1;i<=9;i++) printf(" %lld",ans2.a[i]-ans1.a[i]);
 return 0;
}
 



 

你可能感兴趣的:(bzoj 1833 数字计数|数位dp)