#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);
}
}
}
HDU 3943 数位DP
最新推荐文章于 2017-09-30 08:43:12 发布