Description
给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
题解:
状态还是比较好设计的,关键是转移。一直没有想到怎么转移,看了题解后恍然大悟。只要我们枚举当前的数字和,那么就相当好转移了,因为每一次的模数都是一样的。状态表示以及转移看代码。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=162;
LL f[20][165][165][2];//第i位 数字之和为j %当前数字和为k 是(0)否(1)小于当前数
LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
LL b[20];
LL solve(LL x)
{
int ll=0;LL t=x;
while(t){b[++ll]=t%10;t/=10;}
reverse(b+1,b+1+ll);
LL re=0;
for(int sum=1;sum<=N;sum++)//枚举当前数字和
{
memset(f,0,sizeof(f));
f[0][0][0][1]=1;
for(int i=0;i<ll;i++)
for(int j=0;j<=sum;j++)
for(int k=0;k<N;k++)
for(int l=0;l<2;l++)
if(f[i][j][k][l])
{
for(int m=0;m<=((l==0)?9:b[i+1]);m++)
f[i+1][j+m][(k*10+m)%sum][((l==1&&b[i+1]==m)?1:0)]+=f[i][j][k][l];
}
re+=f[ll][sum][0][0]+f[ll][sum][0][1];
}return re;
}
int main()
{
LL a=read(),b=read();
printf("%lld",solve(b)-solve(a-1));
}