hdu4389

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);
    }
}
原文地址:https://www.cnblogs.com/fxq1304/p/14546524.html