【bzoj1799】【AHOI2009】【同类分布】【数位dp】

来源:互联网 发布:mfc图形界面编程实例 编辑:程序博客网 时间:2024/05/16 05:40

Description

给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。

Input

Output

Sample Input

10 19

Sample Output

3

HINT

【约束条件】1 ≤ a ≤ b ≤ 10^18

题解:

         枚举模数p.

         设f[i][j][k][g]表示第i位,前i位的和为j,当前模p的值为k,到第i位是否比原数小.

         枚举所有状态向后转移即可.

代码:

#include<iostream>#include<cstdio>#include<cstring>#define ll long longusing namespace std;ll pow[20],f[20][200][200][2],l,r;int p[20],num,mx;ll cal(ll x){   ll ans=0;mx=0;num=0;   while (x){p[++num]=x%10;x/=10;}   for (int i=1;i<=num/2;i++) swap(p[i],p[num-i+1]);   for (int i=1;i<=num;i++) mx+=9;   for (int md=1;md<=mx;md++){     memset(f,0,sizeof(f));     f[0][0][0][1]=1; for (int i=0;i<num;i++)       for (int j=0;j<=md;j++)         for (int k=0;k<md;k++)           for (int g=0;g<=1;g++)             if (f[i][j][k][g])               for (int a=0;a<=9;a++){                 int x,y,z;                 if (g&&a>p[i+1]) continue;                 x=j+a;y=(k+(pow[num-(i+1)]%(ll)md)*a%md)%md;                 z=(g&&(a==p[i+1]))?1:0;                 f[i+1][x][y][z]+=f[i][j][k][g];               }     ans+=f[num][md][0][0]+f[num][md][0][1];   }    return ans;}int main(){  pow[0]=1;  for (int i=1;i<=18;i++) pow[i]=pow[i-1]*(ll)10;  scanf("%lld%lld",&l,&r);  printf("%lld\n",cal(r)-cal(l-1));   }


0 0