题解 P1814 【数的序号】
这是一道令人谔谔的数学题(?
如果我们记
即,去掉根之后考虑左右点的个数。
随便打个表就知道
我们首先对输入的
这一步处理很好写:
int n=1;while(x>c[n]) {x-=c[n];++n;}
之后考虑实现 void print(ll x,int n)。
按照题目要求,编号按左子树排序,相等则按右子树排序。
而树先按大小排序,因此我们可以先计算出左子树和右子树的大小,以及在这个大小下要求的树是第几个。
这部分的代码:
int l=0;while(x>c[l]*c[n-1-l]) {x-=c[l]*c[n-1-l];++l;}int r=n-1-l;
接下来,如果用
不难发现,其中第
于是特判
复杂度我不会算,反正常数级别。
void print(ll x,int n)
{
int l=0;while(x>c[l]*c[n-1-l]) {x-=c[l]*c[n-1-l];++l;}int r=n-1-l;
if(l) {putchar('(');print((x-1)/c[r]+1,l);putchar(')');}
putchar('X');
if(r) {putchar('(');print((x-1)%c[r]+1,r);putchar(')');}
}
int main()
{
/* prework for c[i] */
while(true)
{
ll x=rd();
if(!x) break;
int n=1;while(x>c[n]) {x-=c[n];++n;}
print(x,n);
putchar('\n');
}
return 0;
}