传送门:【HDU】3943 K-th Nya Number
题目分析:数位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 ; }