题目分析:数位DP预处理出每一个状态下数的个数,然后每次询问就递推一下。dp数组记录了之前是从哪个数字过来时可以比较方便的处理本题。这题代码应该是被我写复杂了= =。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
typedef long long LL ;
#pragma comment(linker, "/STACK:16777216")
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define now cur][j][flag][four][seven
LL dp[20][10][2][21][21] ;
int vis[20][10][2][21][21] , Time ;
LL ten[20] ;
int digit[20] , n1 ;
int x , y ;
LL kth , ans , sum ;
LL dfs ( int cur , int j , int flag , int four , int seven ) {
if ( vis[now] == Time ) return dp[now] ;
vis[now] = Time ;
if ( !cur ) return dp[now] = ( four == x && seven == y ) ;
LL& ans = dp[now] = 0 ;
if ( flag ) {
rep ( i , 0 , 10 ) ans += dfs ( cur - 1 , i , 1 , four + ( i == 4 ) , seven + ( i == 7 ) ) ;
} else {
rep ( i , 0 , digit[cur] ) ans += dfs ( cur - 1 , i , 1 , four + ( i == 4 ) , seven + ( i == 7 ) ) ;
ans += dfs ( cur - 1 , digit[cur] , 0 , four + ( digit[cur] == 4 ) , seven + ( digit[cur] == 7 ) ) ;
}
return ans ;
}
LL deal ( LL n ) {
n1 = 0 ;
while ( n ) {
digit[++ n1] = n % 10 ;
n /= 10 ;
}
++ Time ;
LL ans = dfs ( n1 , 0 , 0 , 0 , 0 ) ;
return ans ;
}
void dfs2 ( int cur , int j , int flag , int four , int seven ) {
if ( !cur ) return ;
int i ;
if ( flag ) {
for ( i = 0 ; i < 10 ; ++ i ) {
LL tmp = sum + dp[cur - 1][i][1][four + ( i == 4 )][seven + ( i == 7 )] ;
if ( tmp < kth ) sum = tmp ;
else break ;
if ( i == 9 ) break ;
}
ans += i * ten[cur - 1] ;
dfs2 ( cur - 1 , i , 1 , four + ( i == 4 ) , seven + ( i == 7 ) ) ;
} else {
for ( i = 0 ; i <= digit[cur] ; ++ i ) {
LL tmp = sum + dp[cur - 1][i][i != digit[cur]][four + ( i == 4 )][seven + ( i == 7 )] ;
if ( tmp < kth ) sum = tmp ;
else break ;
if ( i == digit[cur] ) break ;
sum = tmp ;
}
ans += i * ten[cur - 1] ;
dfs2 ( cur - 1 , i , i != digit[cur] , four + ( i == 4 ) , seven + ( i == 7 ) ) ;
}
}
void solve () {
int n ;
LL P , Q ;
scanf ( "%I64d%I64d%d%d" , &P , &Q , &x , &y ) ;
LL cnt1 = deal ( P ) ;
LL cnt2 = deal ( Q ) ;
scanf ( "%d" , &n ) ;
while ( n -- ) {
scanf ( "%I64d" , &kth ) ;
kth += cnt1 ;
if ( cnt2 < kth ) {
printf ( "Nya!\n" ) ;
continue ;
}
sum = ans = 0 ;
dfs2 ( n1 , 0 , 0 , 0 , 0 ) ;
printf ( "%I64d\n" , ans ) ;
}
}
int main () {
int T , cas = 0 ;
clr ( vis , 0 ) ;
Time = 0 ;
ten[0] = 1 ;
rep ( i , 1 , 20 ) ten[i] = ten[i - 1] * 10 ;
scanf ( "%d" , &T ) ;
while ( T -- ) {
printf ( "Case #%d:\n" , ++ cas ) ;
solve () ;
}
return 0 ;
}