종말 언젠가

종말 언젠가

중간 연속 적어도 하나는 6 세보다 큰 경우에만 나타나는 경우에는 번호가 유효 정의는 x 번째의 유효 숫자를 찾 \ (X \ 당량 50,000,000 \)

해결

첫째, 테스트 채우기 방법을 생각하고, 중요한 방법을 채우기 위해 시도하는 여러 가지의 첫째을 추구 통지이 기억이 상태에서 프로그램의 수를 결정하는 것입니다, 그것은 잘 이해된다.

성능 분명히 길이뿐만 아니라 인해 합법적의 성능, 다음 설정 \는 (F는 [I]는 [j는 ] \) (0은 가장 중요한 비트는 6,1 6,2 나타내는없는 나타내는 상태가 J이고, 숫자 나 비트가 나타낸다 두 연속적인 잘못된 번호 6 3이있는이 프로그램 번호의 합법적 번호) 인 것을 나타내며, 매우 곤란이 없다

\ [F [I] [0] = (F [I-1] [0] + F에 [I-1] [1] + F [I-1] [2]) \ 시간 9 \]

\ [F는 [I] [1] F = [I-1] [0], F [i]는 [2] = F [I-1] [1], F [i]는 [3] = 10 \ 시간 F [I-1] [3] + F에 [I-1] [2] \]

테두리 : \. (F [0] [0] = 1 \)

그래서 우리는 비트를 채우기 위해 등 많은 관심 공보 문장 (6), 작은에서, 낮은 높은에서이 시험을 채울 수 있습니다 내가 어디 내가 옆에 두 개의 연속 6 비트의 앞에 채우기 6, 다음 만 \ ([I-1] (F) [3] \) 정당한 프로그램뿐만 아니라, 같은 \ (F의 [. 1-I]. 1] + F [-I. 1] [2] \) , 동일한 이유로 참고 선행 3개월에서 전방 릴리스 6,6이없이 여기 채우기 프로그램이 무엇 없다 \ (F [I-1] [0] + F [I-1] [1] + F [I-1] [2] + F [Ⅰ- 1] [3] \)

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define int long long
using namespace std;
int dp[21][4];
il int max(int,int);
il void read(int&),prepare();
main(){
    int lsy;read(lsy),prepare();
    while(lsy--){
        int x;read(x);
        int w(0),i,j,t6(0),cnt;
        while(dp[w][3]<x)++w;
        while(w){
            for(i=0;i<10;++i){
                cnt=dp[w-1][3];
                if(i==6||t6>2)
                    for(j=max(2-t6,0);j<3;++j)
                        cnt+=dp[w-1][j];
                if(cnt>=x){putchar(i+48);break;}
                else x-=cnt;
            }if(i==6)++t6;else if(t6<3)t6&=0;--w;
        }putchar('\n');
    }
    return 0;
}
il int max(int a,int b){
    return a>b?a:b;
}
il void prepare(){
    dp[0][0]=1;
    for(int i(1);i<=20;++i)
        dp[i][1]=dp[i-1][0],dp[i][2]=dp[i-1][1],dp[i][3]=10*dp[i-1][3]+dp[i-1][2],
            dp[i][0]=(dp[i-1][0]+dp[i-1][1]+dp[i-1][2])*9;
}
il void read(int &x){
    x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

추천

출처www.cnblogs.com/a1b3c7d9/p/10992509.html