数位DP加二分
//数位dp,dfs记忆化搜索 #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; #define N 20 LL dp[N][3];//dp[i][j]表示长度为i,前面有j个6时不含666的数的个数 int num[N]; //c6表示前面6的个数 LL dfs(int len, int c6, bool ismax){ if(len == 0){ return 1; } if(!ismax && dp[len][c6] >= 0){ return dp[len][c6]; } int max = ismax? num[len]:9; LL cnt = 0; for(int i = 0; i <= max; i++){ if(c6 == 2 && i == 6){ continue; } cnt += dfs(len-1, i == 6? c6 + 1: 0, ismax && i == max); } return ismax?cnt:dp[len][c6]=cnt; } LL solve(LL n){ LL t = n; int len = 0; while(n){ num[++len]=n%10; n/=10; } return t + 1 - dfs(len, 0, true); } int main(){ memset(dp,-1,sizeof(dp)); int t; cin>>t; while(t--){ LL n; scanf("%I64d", &n); LL l = 666, r = 50000000666ll; while(l < r){ LL m = (l + r)>>1; if(solve(m) < n){ l = m + 1; }else{ r = m; } } printf("%I64d ", l); } return 0; }