hdu 4389 X mod f(x)(数位dp)

Problem Description
Here is a function f(x):
   int f ( int x ) {
    if ( x == 0 ) return 0;
    return f ( x / 10 ) + x % 10;
   }

   Now, you want to know, in a given interval [A, B] (1 <= A <= B <= 109), how many integer x that mod f(x) equal to 0.
 

 

Input
   The first line has an integer T (1 <= T <= 50), indicate the number of test cases.
   Each test case has two integers A, B.
 

 

Output
   For each test case, output only one line containing the case number and an integer indicated the number of x.
 
题意:让你求A~B之间有几个数mod自身各个位数之和为0.
 
显然是一道数位dp,设dp[len][count][mod][mm](表示前len位各位数和为count,余mm,余数为mod),由于数据不超过
10^9,所以count最大不超过81。所以mm也不大于81.
 
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int dp[10][82][82][82] , a[12] , mm;
int dfs(int len , int mod , int temp , int flag) {
    if(len == 0) {
        return temp == mm && mod == 0;
    }
    if(!flag && dp[len][temp][mod][mm] != -1) {
        return dp[len][temp][mod][mm];
    }
    int n = flag ? a[len] : 9;
    int sum = 0;
    for(int i = 0 ; i <= n ; i++) {
        if(temp + i <= mm)
            sum += dfs(len - 1 , (mod * 10 + i) % mm , temp + i , flag && i == n);
    }
    if(!flag) {
        dp[len][temp][mod][mm] = sum;
    }
    return sum;
}
int Get(int x) {
    memset(a , 0 , sizeof(a));
    //memset(dp , -1 , sizeof(dp));
    int len = 0;
    if(x == 0) {
        len = 1;
    }
    while(x) {
        a[++len] = x % 10;
        x /= 10;
    }
    return dfs(len , 0 , 0 , 1);
}
int main()
{
    int t;
    cin >> t;
    memset(dp , -1 , sizeof(dp));
    int ans = 0;
    while(t--) {
        int n , m;
        ans++;
        cin >> n >> m;
        int sum = 0;
        for(mm = 1 ; mm <= 81 ; mm++) {
            sum += Get(m) - Get(n - 1);
        }
        cout << "Case " << ans << ": " << sum << endl;
    }
    return 0;
}
posted @ 2016-11-15 10:58  Gealo  阅读(145)  评论(0编辑  收藏  举报