HDU 4507 数位dp

 先保存一下代码,回头写题解。

 

 

 

 

 

 

 

 

 

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

const int MOD = 1e9+7;

struct node {
    LL num, sum, ssum;
    node() {}
    node(LL a, LL b, LL c) : num(a), sum(b), ssum(c) {}
}dp[21][2][7][7];

int digit[21];
int len;

int getlen(LL x) {
    int ret = 0;
    while(x) {
        digit[++ret] = x%10;
        x /= 10;
    }
    return ret;
}

void init() {
    for(int i = 0; i < 21; ++i) {
        for(int j = 0; j < 2; ++j) {
            for(int k = 0; k < 7; ++k) {
                for(int l = 0; l < 7; ++l) {
                    dp[i][j][k][l] = node(0, 0, 0);
                }
            }
        }
    }
}

void solve() {
    int p, d, i, j, ii, jj;
    for(p = len; p > 0; --p) {
        for(d = 0; d < 10; ++d) {
            if(d == 7)  continue;
            for(i = 0; i < 7; ++i) {
                for(j = 0; j < 7; ++j) {
                    ii = (i + d)%7;
                    jj = (j*10 + d)%7;
                    //
                    dp[p][1][ii][jj].sum += dp[p+1][1][i][j].sum*10 + dp[p+1][1][i][j].num*d;
                    if(d < digit[p])
                        dp[p][1][ii][jj].sum += (dp[p+1][0][i][j].sum*10 + dp[p+1][0][i][j].num*d);
                    dp[p][1][ii][jj].sum %= MOD;
                    //
                    dp[p][1][ii][jj].num += dp[p+1][1][i][j].num;
                    if(d < digit[p])
                        dp[p][1][ii][jj].num += dp[p+1][0][i][j].num;
                    dp[p][1][ii][jj].num %= MOD;
                    //
                    dp[p][1][ii][jj].ssum += dp[p+1][1][i][j].ssum*100LL + 20LL*dp[p+1][1][i][j].sum*d + dp[p+1][1][i][j].num*d*d;
                    if(d < digit[p])
                        dp[p][1][ii][jj].ssum += dp[p+1][0][i][j].ssum*100LL + 20LL*dp[p+1][0][i][j].sum*d + dp[p+1][0][i][j].num*d*d;
                    dp[p][1][ii][jj].ssum %= MOD;
                }
            }
        }
        d = digit[p];
        if(d == 7)  continue;
        for(i = 0; i < 7; ++i) {
            for(j = 0; j < 7; ++j) {
                if(!dp[p+1][0][i][j].num)   continue;
                ii = (i + d)%7;
                jj = (j*10 + d)%7;
                //
                dp[p][0][ii][jj].sum += dp[p+1][0][i][j].sum*10 + dp[p+1][0][i][j].num*d;
                dp[p][0][ii][jj].sum %= MOD;
                //
                dp[p][0][ii][jj].num += dp[p+1][0][i][j].num;
                dp[p][0][ii][jj].num %= MOD;
                //
                dp[p][0][ii][jj].ssum += dp[p+1][0][i][j].ssum*100LL + 20LL*dp[p+1][0][i][j].sum*d + dp[p+1][0][i][j].num*d*d;
                dp[p][0][ii][jj].ssum %= MOD;
            }
        }
    }
}

LL cal(LL x) {
    init();
    len = getlen(x);
    dp[len+1][0][0][0].num = 1;
    solve();
    LL ans = 0;
    for(int i = 1; i < 7; ++i) {
        for(int j = 1; j < 7; ++j) {
            ans = (ans + dp[1][1][i][j].ssum)%MOD;
            ans = (ans + dp[1][0][i][j].ssum)%MOD;
        }
    }
    return ans%MOD;
}

int main() {
    //Read();

    int T;
    LL a, b, ans;
    cin >> T;
    while(T--) {
        cin >> a >> b;
        ans = cal(b) - cal(a - 1);
        cout << (ans + MOD)%MOD << endl;
    }
    return 0;
}

 

你可能感兴趣的:(HDU 4507 数位dp)