HDU 3943 K-th Nya Number

Problem Description
Arcueid likes nya number very much.
A nya number is the number which has exactly X fours and Y sevens(If X=2 and Y=3 , 172441277 and 47770142 are nya numbers.But 14777 is not a nya number ,because it has only 1 four).
Now, Arcueid wants to know the K-th nya number which is greater than P and not greater than Q.

Input
The first line contains a positive integer T (T<=100), indicates there are T test cases.
The second line contains 4 non-negative integers: P,Q,X and Y separated by spaces.
( 0<=X+Y<=20 , 0< P<=Q <2^63)
The third line contains an integer N(1<=N<=100).
Then here comes N queries.
Each of them contains an integer K_i (0

#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <utility>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
const int maxn = 30;
ll dp[maxn][10][22][22];
int T, X, Y, N;
ll P, Q, K;

void init() {
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i <= 9; ++i) {
        if(i == 4) {
            dp[1][4][1][0] = 1;
        } else if(i == 7) {
            dp[1][7][0][1] = 1;
        } else {
            dp[1][i][0][0] = 1;
        }
    }
    for(int i = 2; i <= 20; ++i) {
        for(int j = 0; j <= 9; ++j) {
            for(int x1 = 0; x1 <= 20; ++x1) {
                for(int x2 = 0; x2 <= 20; ++x2) {
                    for(int k = 0; k <= 9; ++k) {
                        if(j == 4) {
                            if(x1 > 0) {
                                dp[i][j][x1][x2] += dp[i-1][k][x1-1][x2];
                            } else {
                                dp[i][j][x1][x2] = 0;
                            }
                        } else if(j == 7) {
                            if(x2 > 0) {
                                dp[i][j][x1][x2] += dp[i-1][k][x1][x2-1];
                            } else {
                                dp[i][j][x1][x2] = 0;
                            }
                        } else {
                            dp[i][j][x1][x2] += dp[i-1][k][x1][x2];
                        }
                    }
                }
            }
        }
    }
    return ;
}
int bit[30], blen;

bool check(int x, int y) {
    for(int i = 0; i < blen; ++i) {
        if(bit[i] == 4) x--;
        if(bit[i] == 7) y--;
    }
    return x == 0 && y == 0;
}

ll dfs(ll pos, int num4, int num7) {
    if(pos < 0) {
        return check(X, Y) ? 1 : 0;
    }
    if(num4 < 0) return 0;
    if(num7 < 0) return 0;
    ll ret = 0;
    for(int i = 0; i < bit[pos]; ++i) {
        ret += dp[pos+1][i][num4][num7];
    }
    if(bit[pos] == 4) num4--;
    if(bit[pos] == 7) num7--;
    ret += dfs(pos - 1, num4, num7);
    return ret;
}

ll solve(ll x) {
    blen = 0;
    while(x) {
        bit[blen++] = x % 10;
        x /= 10;
    }
    return dfs(blen-1, X, Y);
}

int main() {

    //freopen("aa.in", "r", stdin);
    init();
    int kcase = 0;
    ll n1, n2, ans;
    scanf("%d", &T);
    while(T--) {
        kcase++;
        scanf("%I64d %I64d %d %d", &P, &Q, &X, &Y);
        n1 = solve(P);
        scanf("%d", &N);
        printf("Case #%d:\n", kcase);
        for(int i = 1; i <= N; ++i) {
            scanf("%I64d\n", &K);
            ll l = P + 1, r = Q, mid;
            ans = -1;
            while(l <= r) {
                mid = (l + r) / 2;
                n2 = solve(mid);
                if(n2 - n1 >= K) {
                    if(ans == -1) ans = mid;
                    else ans = min(ans, mid);
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }
            if(ans == -1) {
                printf("Nya!\n");
            } else {
                printf("%I64d\n", ans);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值