hdu4389
hdu4389 X mod f(x)
传送门
题意
计算区间\([A,B](1\leq A\leq B\leq 1e9)\)中,能被自己各个数位之和整除的数的个数。
题解
数位\(dp\)。
各个数位之和的范围为\([1,81]\),对于每一个和,数位\(dp\)计算满足条件的数的个数。
\(dp[i][x][rest][sum]\)表示从高位到低位直到第\(i\)位数,当前的数模\(x\)的余数是\(rest\),各个数位之和为\(sum\)的数的个数。
#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define LD long double
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PLI pair<LL,int>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
int T,a,b,bit[10],dp[10][82][82][82];
int divide(int x){
int cnt=0;
while(x){
bit[cnt++]=x%10;
x/=10;
}
return cnt;
}
int dfs(int pos,int x,int rest,int sum,bool limit){
if(pos==-1) return rest==0 && sum==x;
if(!limit && dp[pos][x][rest][sum]!=-1) return dp[pos][x][rest][sum];
int up=limit?bit[pos]:9;
int ans=0;
for(int i=0;i<=up;i++){
ans+=dfs(pos-1,x,(rest*10+i)%x,sum+i,limit && i==up);
}
if(!limit) dp[pos][x][rest][sum]=ans;
return ans;
}
int main(){
memset(dp,-1,sizeof(dp));
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d %d",&a,&b);
int cnt1=divide(a-1);
LL ans1=0;
for(int i=1;i<=81;i++){
ans1+=dfs(cnt1-1,i,0,0,1);
}
int cnt2=divide(b);
LL ans2=0;
for(int i=1;i<=81;i++){
ans2+=dfs(cnt2-1,i,0,0,1);
}
printf("Case %d: %d\n",cas,ans2-ans1);
}
}