hdu4389 X mod f(x)
传送门
题意
计算区间([A,B](1leq Aleq Bleq 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
",cas,ans2-ans1);
}
}