//#pragma GCC optimize("O3") #include using namespace std; #define ll long long #define rep(i,n) for (ll i=0;i<(ll)(n);i++) #define rrep(i,n) for (ll i=(ll)(n)-1;i>=0;i--) #define loop(i,m,n) for(ll i=(m);i<=(ll)(n);i++) void solve(){ ll M; cin>>M; const ll N=40; vector ans(N,string(N,'#')); // 本線 // -2 <= i-j <= 3 の斜め帯を作る。 // 右下では合流路と干渉しないように途中で切る。 rep(i,N){ rep(j,N){ if(-2<=i-j && i-j<=3 && i+j<=72){ ans[i][j]='.'; } } } // 本線内で、(0,0) から各マスまでの最短経路数を求める。 vector> dp(N,vector(N,0)); dp[0][0]=1; rep(i,N){ rep(j,N){ if(i==0 && j==0)continue; if(ans[i][j]=='#')continue; if(i>0)dp[i][j]+=dp[i-1][j]; if(j>0)dp[i][j]+=dp[i][j-1]; } } // {その出口を使ったときに増える経路数, 出口座標} vector>> exits; // 上側の出口候補 // 本線境界 (i,i+2) の右隣 (i,i+3) rep(i,36){ exits.push_back({ dp[i][i+2], {i,i+3} }); } // 下側の出口候補 // 本線境界 (j+3,j) の下隣 (j+4,j) rep(j,35){ exits.push_back({ dp[j+3][j], {j+4,j} }); } sort(exits.begin(),exits.end()); // 各重みまでの部分和で、隙間なく全整数が作れることを確認。 ll sum=0; for(auto [v,p]:exits){ assert(v<=sum+1); sum+=v; } assert(sum==1406601707949008441LL); assert(M<=sum); // 上側出口からゴールへ向かう合流路 // // (i,i+3) が出口。 // (i,i+4) -> (i,i+5) -> (i+1,i+5) -> ... rep(i,36){ ans[i][i+4]='.'; } rep(i,35){ ans[i][i+5]='.'; } // 右端へ接続 loop(i,35,39){ ans[i][39]='.'; } // 下側出口からゴールへ向かう合流路 rep(j,35){ ans[j+5][j]='.'; } rep(j,34){ ans[j+6][j]='.'; } // 下端へ接続 loop(j,34,39){ ans[39][j]='.'; } // M を出口の重みの部分和として表す。 // v_k <= 1 + sum_{i>T; rep(_,T){ solve(); } }