当前位置: 代码迷 >> 综合 >> bzoj 1799: [Ahoi2009]self 同类分布
  详细解决方案

bzoj 1799: [Ahoi2009]self 同类分布

热度:52   发布时间:2023-10-29 10:29:29.0

题意

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

题解

枚举那些数加起来是多少,最大是9*18
然后你就可以数位DP了。。
有剩下的数,当前的余数是多少。。
然后就没有了

#include<cstdio>
#include<cstring>
typedef long long LL;
LL A,B;
LL n;
LL ans=0;
LL a[20],o;
LL P;//模数是什么
LL f[20][9*19][9*19][2]; 
LL get (LL now,LL x,LL y,bool tf)//现在到第几位 现在的余数是多少 剩下的是多少 是否出现了第一个不同 
{if (y<0) return 0;if (now<=0){if (y==0&&x==0) return 1;return 0;}if (f[now][x][y][tf]!=-1) return f[now][x][y][tf];LL lalal=0;if (tf==false)//不可以越界 {lalal=lalal+get(now-1,(x*10%P+a[now])%P,y-a[now],false);for (LL u=0;u<a[now];u++)//这一位填什么lalal=lalal+get(now-1,(x*10%P+u)%P,y-u,true); }else{for (LL u=0;u<=9;u++)lalal=lalal+get(now-1,(x*10%P+u)%P,y-u,true);}f[now][x][y][tf]=lalal;return f[now][x][y][tf];
}    
LL solve (LL x)
{n=x;ans=0;o=0;while (x>0){a[++o]=x%10;x/=10;}for (LL u=1;u<=9*o;u++)//数位的总和是什么{memset(f,-1,sizeof(f));P=u;ans=ans+get(o,0,u,false);}return ans;
}
int main()
{scanf("%lld%lld",&A,&B);
/* for (LL u=1;u<=20;u++)printf("%lld\n",solve(u));*/printf("%lld\n",solve(B)-solve(A-1));return 0;
}