天天看點

(數位dp)ZOJ 3962 Seven Segment Display

部落格

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define ll long long
#define lb long double
#define INF 0x3f3f3f3f
const int maxn = 100035;
const int mod = 1e6 + 7;
int t, len;
ll n;
int a[20];
char s[10];
ll dp[10][500], kkk = (ll)0xffffffff + 1;
int p[20] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6, 6, 5, 4, 5, 5, 4};
ll dfs(int pos, int limit, ll sum){
    if(pos == 0) return sum;
    if(dp[pos][sum] != -1 && !limit) return dp[pos][sum];
    ll ret = 0;
    int res = limit ? a[pos] : 15;
    for(int i = 0 ; i <= res ; ++ i){
        ret += dfs(pos - 1, i == res && limit, sum + p[i]);
    }
    return (!limit) ? dp[pos][sum] = ret : ret;
}
ll part(ll n){
    len = 0;
    memset(a, 0, sizeof(a));
    while(n){
        a[++len] = n % 16;
        n /= 16;
    }
    return dfs(8, 1, 0);
}
int main()
{
    scanf("%d", &t);
    memset(dp, -1, sizeof(dp));
    while(t--){
        scanf("%lld%s", &n, s+1);
        ll l = 0;
        for(int i = 1 ; i <= 8 ; ++ i){
            if(s[i] <= '9' && s[i] >= '0') l = l * 16 + s[i] - '0';
            else l = l * 16 + s[i] - 'A' + 10;
        }
        if(l + n - 1 >= kkk){
            ll r = (l + n - 1) % kkk;
            printf("%lld\n", part(kkk-1) - (part(l-1) - part(r)));
        }
        else{
            ll r = l + n - 1;
            printf("%lld\n", part(r) - part(l-1));
        }
    }
    return 0;
}