emmm我又来啦
注释见代码
//也就是希望能帮到一些跟我一样看不懂代码的人儿qwq
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 21;
ll f[N][3], g[N];
void init()
{
//f[i][j]: 由i个数构成的左边(高位)有j个6的数的个数
//g[i]: 由i个数构成魔鬼数的个数
f[0][0] = 1;
f[0][1] = f[0][2] = 0;
g[0] = 0;
for (int i = 1; i < N; i++)
{
f[i][0] = 9 * (f[i - 1][0] + f[i - 1][1] + f[i - 1][2]);//左边有0个6,只要这个数不选6就行
f[i][1] = f[i - 1][0];
f[i][2] = f[i - 1][1];//最左边只能选6
g[i] = 10 * g[i - 1] + f[i - 1][2];//由后面i - 1个数构成666,或者最左边选6再加两个6
}
}
int main()
{
init();
int t, x;
cin >> t;
while (t--)
{
cin >> x;
int m = 3;//先确定这个数的位数
while (g[m] < x)
m++;
for (int i = m, k = 0; i > 0; i--)//从左到右(从高位到低位)枚举
//k记录左边有多少个连续的6,k = 3代表已经出现过666
{
for (int j = 0; j <= 9; j++)
{
//计算i个数构成,且最左边是j的魔鬼数的个数
ll cnt = g[i - 1];
//现在左边已经有k + (j == 6)个6,还差3 - k - (j == 6)个
//或者前面已经有三个连续的6,一定是魔鬼数
if (j == 6 || k == 3)
for (int l = max(3 - k - (j == 6), 0); l < 3; l++)
cnt += f[i - 1][l];
if (cnt >= x)
{
cout << j;
if (k < 3)
{
if (j == 6) k++;
else k = 0;
}
break;
}
else x -= cnt;
}
}
cout << endl;
}
return 0;
}
max函数写的很细节,后面if里面套个if很棒
%%%
$666$