HDU 3943 数位DP

来源:互联网 发布:家政网络平台 编辑:程序博客网 时间:2024/05/19 00:47
#include <cstdlib>#include <cctype>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <string>#include <iostream>#include <sstream>#include <map>#include <set>#include <queue>#include <stack>#include <fstream>#include <numeric>#include <iomanip>#include <bitset>#include <list>#include <stdexcept>#include <functional>#include <utility>#include <ctime>#include <cassert>#include <complex>using namespace std;typedef long long ll;typedef long double ld;const int int_max = 0x07777777;const int int_min = 0x80000000;const int inf=0x20202020;const ll mod=1000000007;const double eps=1e-9;const double pi=3.1415926535897932384626;const int DX[]={1,0,-1,0},DY[]={0,1,0,-1};ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}ll dp[30][21][21];ll p,q,x,y,a[30];ll getcount (int len){    ll sum = 0;    int xx=0, yy=0;    for(int i = len; i >= 1; i--){        for(int j = 0; j <a[i]; j++){            if(j==4){                if(xx<x) sum += dp[i-1][x-xx-1][y-yy];                continue;            }            if(j==7) {                if(yy<y) sum += dp[i-1][x-xx][y-yy-1];                continue;            }            sum += dp[i-1][x-xx][y-yy];        }        if(a[i]==4) xx++;        if(a[i]==7) yy++;        if(xx>x || yy>y) break;    }    return sum;}ll solve (ll x){    for(int i = 0; i < 30; i++) a[i] = 0;    int len = 0;    while(x){        a[++len] = x%10;        x /= 10;    }    ll ret = getcount(len);    return ret;}bool check (ll num){    int xx = 0, yy = 0;    while(num){        int t = num%10;        if(t==4) xx++;        if(t==7) yy++;        num /= 10;    }    if(xx==x && yy==y) return true;    return false;}long long Solve(long long k){    int len=1;    while(1){        if(dp[len-1][x][y]<k && dp[len][x][y]>=k)   //找到目标数的长度            break;        len++;    }    long long res=0;    int cx=x,cy=y;    for(int i=len;i>0;i--)   //从高位开始从小枚举        for(int j=0;j<10;j++){            int tx=cx,ty=cy;            if(j==4){                tx--;                if(tx<0)                    continue;            }            if(j==7){                ty--;                if(ty<0)                    continue;            }            if(dp[i-1][tx][ty]>=k){                res=res*10+j;                cx=tx;                cy=ty;                break;            }            k-=dp[i-1][tx][ty];        }    return res;}int main(){    for(int i = 0; i < 30; i++){        for(int j = 0; j < 21; j++){            for(int k = 0; k < 21; k++) dp[i][j][k] = 0;        }    }    dp[0][0][0] = 1;    for(int i = 1; i < 30; i++){        for(int j = 0; j < 21; j++){            for(int k = 0; k <21; k++){                dp[i][j][k] += dp[i-1][j][k]*8;                if(j>0) dp[i][j][k] += dp[i-1][j-1][k];                if(k>0) dp[i][j][k] += dp[i-1][j][k-1];            }        }    }    int T;    scanf("%d", &T);    int cntt = 1;    while(T--){        printf("Case #%d:\n",cntt++);        scanf("%I64d%I64d%I64d%I64d",&p,&q,&x,&y);        int n;        scanf("%d", &n);        ll first = solve(p+1);        ll second = solve(q+1);        for(int i = 0; i < n; i++){            ll k;            scanf("%I64d",&k);            int len=1;            if(first+k > second) {                printf("Nya!\n");                continue;            }            k = first+k;            while(1){            if(dp[len-1][x][y]<k && dp[len][x][y]>=k)   //找到目标数的长度                break;            len++;            }            long long res=0;            int cx=x,cy=y;            for(int i=len;i>0;i--)   //从高位开始从小枚举                 for(int j=0;j<10;j++){            int tx=cx,ty=cy;            if(j==4){                tx--;                if(tx<0)                    continue;            }            if(j==7){                ty--;                if(ty<0)                    continue;            }            if(dp[i-1][tx][ty]>=k){                res=res*10+j;                cx=tx;                cy=ty;                break;            }            k-=dp[i-1][tx][ty];        }            printf("%I64d\n", res);        }    }}

0 0
原创粉丝点击