题目
题目链接:http://noip.ybtoj.com.cn/contest/102/problem/2
输入保证答案一定存在,你输出的 (n) 必须是正整数且不得超过 60。对每个询问,你只需要输出任意一个合法解即可。
思路
考虑已知的一个以 (x) 为根的有 (k) 个与 (x) 连接的连通块,此时如果我们给 (x) 加一个儿子,那么连通块数量变成 (2k);如果加上一个父亲 (y),那么以 (y) 为根的连通块就有 (k+1) 个。
那么任意一个数 (x) 都可以通过 (2log x) 次操作得出,所以最多需要使用 (2log(10^9)leq 60) 次操作。
时间复杂度 (O(Tlog n))。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=65;
int n,m,tot,ans[N][2];
void dfs(int k,int rt)
{
if (k==1) return;
ans[++m][0]=rt; ans[m][1]=++tot;
if (k&1) dfs(k-1,tot);
else dfs(k/2,rt);
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
while (scanf("%d",&n)!=EOF)
{
m=0; tot=1;
dfs(n,1);
printf("%d
",m+1);
for (int i=1;i<=m;i++)
printf("%d %d
",ans[i][0],ans[i][1]);
}
return 0;
}