4135: [FJOI2015]世界树
Time Limit: 15 Sec Memory Limit: 32 MBSubmit: 25 Solved: 12
[ Submit][ Status][ Discuss]
Description
奥丁杀死的巨人伊米尔后,从伊米尔的尸体上生长出来一株巨大的梣树,它是整个宇宙的核心,被称为世界之树,这个巨木的枝干构成了整个世界,它被神秘的奥术力量所守护。
奥丁发现,世界树的每个节点至多有两棵子树,其蕴含的奥术力量是子树奥术力量的最大值+1,如果一个节点没有子树,其奥术力量为1,这些节点被称为“源”。
世界树在悠长的岁月里形成了奇妙的魔法平衡,具体来说,它的左子树与右子树的奥术力量的差的绝对值不会超过1。若一个节点只有一棵子树(不妨设为左子树),则右子树的奥术力量视为0。
现在奥丁想知道,在n个节点的世界树中,最高和最低的两个“源”(即叶子节点)的深度差最大是多少?
Input
第一行一个整数T,表示数据组数。
以下T行,每行一个整数n表示世界树的节点数。
Output
T行,每行一个整数表示任意两个“源”的奥术力量的差的最大值。
Sample Input
2
5
12345
5
12345
Sample Output
1
9
9
HINT
对于100%的数据,1 <= n <= 10^10000, T <= 50
Source
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1E4 + 10;
struct N{
int s,num;
short v[maxn];
bool operator < (const N &B) const {
if (s > B.s) return 0;
if (s < B.s) return 1;
for (int i = s; i; i--) {
if (v[i] < B.v[i]) return 1;
if (v[i] > B.v[i]) return 0;
}
return 0;
}
bool operator <= (const N &B) const {
if (s > B.s) return 0;
if (s < B.s) return 1;
for (int i = s; i; i--) {
if (v[i] < B.v[i]) return 1;
if (v[i] > B.v[i]) return 0;
}
return 1;
}
N operator + (const N &b) const {
N ret;
int L = max(s,b.s);
int x = 0;
for (int i = 1; i <= L; i++) {
ret.v[i] = (v[i]+b.v[i]+x) % 10;
x = (v[i]+b.v[i]+x)/10;
}
ret.s = L;
if (x) ret.v[L+1] = x,++ret.s;
return ret;
}
N operator = (const N &b) {
s = b.s;
num = b.num;
for (int i = 1; i <= s; i++) v[i] = b.v[i];
}
}a,b,sum,q[55],su;
char num[maxn];
int ans[55];
int main()
{
#ifdef YZY
freopen("yzy.txt","r",stdin);
#endif
a.v[1] = 1; b.v[1] = 2; sum.v[1] = 3; su.v[1] = 1;
a.s = b.s = sum.s = su.s = 1;
int n; cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%s",num);
int len = strlen(num);
for (int j = len; j; j--) q[i].v[j] = num[len-j]-'0';
q[i].s = len;
q[i].num = i;
int j = 1;
for(;;) {
if (q[i].v[j] >= 1) {
--q[i].v[j];
break;
}
else q[i].v[j] = 9,++j;
}
if (!q[i].v[len]) --q[i].s;
}
sort (q+1,q+n+1);
int tot = 1;
for (int i = 1; i <= n; i++) {
while (sum <= q[i]) {
su = sum; N c;
c = b;
sum = sum+a+b;
b = a+b; a = c; ++tot;
}
ans[q[i].num] = tot/2;
if (q[i].v[1] == 5 && q[i].s == 1) ans[q[i].num] = 0;
}
for (int i = 1; i <= n; i++) printf("%d\n",ans[i]);
return 0;
}