数位DP
状态记录非常麻烦
#include<cstdio>
#include<cstring>
#define N 91
using namespace std;
int n;
int dp[11][N][N][N];//位数,各位和,模,余数
int tmp[11],ten[11];
void init(){
int i,mod,res,sum,now;
ten[0]=1;
for(i=1;i<=10;i++)
ten[i]=ten[i-1]*10;
memset(dp,0,sizeof(dp));
for(i=1;i<=90;i++)
dp[0][0][i][0]=1;
for(i=0;i<=9;i++)
for(mod=1;mod<=90;mod++)
dp[1][i][mod][i%mod]=1;
for(i=2;i<=10;i++)
for(mod=1;mod<=90;mod++)
for(sum=0;sum<=90;sum++)
for(now=0;now<=sum && now<=9;now++)
for(res=0;res<mod;res++)
dp[i][sum][mod][(res*10+now)%mod]+=dp[i-1][sum-now][mod][res];
}
int cal(int a){
int k=1,ans=0,sum=0,pre=0,tem=0,all,i,j,res,aa=a;
if(a<=10)return a;
while(a){
tmp[k]=a%10;
sum+=tmp[k++];
a/=10;
}
k--;
if(aa%sum==0)
ans++;
for(all=1;all<=90;all++){ //枚举和
pre=0,tem=all;
for(i=k;i>=1;i--){ //从高位开始
for(j=0;j<tmp[i] && j<=tem;j++){ //枚举这一位
for(res=0;res<90;res++){ //枚举余数
if((res+j*ten[i-1]+pre)%all==0)
ans+=dp[i-1][tem-j][all][res];
}
}
pre+=tmp[i]*ten[i-1];
tem-=tmp[i];
if(tem<0)break;
}
}
return ans;
}
int main(){
int t,T;
int a,b;
init();
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d %d",&a,&b);
printf("Case %d: %d\n",t,cal(b)-cal(a-1));
}
}