列表

详情


NC19955. [FJOI2015]世界树

描述

奥丁杀死的巨人伊米尔后,从伊米尔的尸体上生长出来一株巨大的梣树,它是整个宇宙的核心,被称为世界之树,这个巨木的枝干构成了整个世界,它被神秘的奥术力量所守护。
奥丁发现,世界树的每个节点至多有两棵子树,其蕴含的奥术力量是子树奥术力量的最大值+1,如果一个节点没有子树,其奥术力量为1,这些节点被称为“源”。 世界树在悠长的岁月里形成了奇妙的魔法平衡,具体来说,它的左子树与右子树的奥术力量的差的绝对值不会超过1。若一个节点只有一棵子树(不妨设为左子树),则右子树的奥术力量视为0。
现在奥丁想知道,在n个节点的世界树中,最高和最低的两个“源”(即叶子节点)的深度差最大是多少?

输入描述

第一行一个整数T,表示数据组数。
以下T行,每行一个整数n表示世界树的节点数。

输出描述

T行,每行一个整数表示任意两个“源”的奥术力量的差的最大值。

示例1

输入:

2
5
12345

输出:

1
9

原站题解

import java.util.Scanner;
public class Main {
public static void main(String[] arg) {
Scanner scanner = new Scanner(System.in);
// todo
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

C++11(clang++ 3.9) 解法, 执行用时: 263ms, 内存消耗: 2244K, 提交时间: 2020-08-28 18:57:46

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
#include<cmath>
#define inf 1000000000
#define rad 100000000
#define pa pair<int,int>
#define ll long long
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char tmp[10005];
string ch;
int bin[20];
struct data{
int l;ll v[2005];
data(){
l=1;
memset(v,0,sizeof(v));
}
inline ll& operator[](int x){
return v[x];
}
friend data operator+(data a,data b){
if(a.l<b.l)swap(a,b);
for(int i=1;i<=b.l;i++)
a[i]+=b[i];
for(int i=1;i<=a.l;i++)
if(a[i]>=rad)
{
if(i==a.l)a.l++;
a[i+1]+=a[i]/rad;
a[i]%=rad;
}
return a;
}
friend data operator*(data a,data b){
data c;
for(int i=1;i<=a.l;i++)
for(int j=1;j<=b.l;j++)
c[i+j-1]+=a[i]*b[j];
for(int i=1;i<=a.l+b.l;i++)
{
if(c[i]>=rad)
{
c[i+1]+=c[i]/rad;
c[i]%=rad;
}
if(c.v[i])c.l=i;
}
return c;
}
friend void print(data a){
for(int i=a.l;i;i--)printf("%.8I64d",a[i]);
puts("");
}
friend bool operator<=(data a,data b){
if(a.l<b.l)return 1;
else if(a.l>b.l)return 0;
for(int i=a.l;i;i--)
if(a[i]<b[i])return 1;
else if(a[i]>b[i])return 0;
return 1;
}
}n;
data get(string ch){
data a;
int t=ch.length();ch=" "+ch;
a.l=(t-1)/8+1;
for(int i=1;i<=a.l;i++)
{
ll k=1;
for(int j=1;j<=8;j++)
{
if(t-8*(i-1)-j+1>=1)
a[i]+=k*(ch[t-8*(i-1)-j+1]-'0');
k*=10;
}
}
return a;
}
struct M{
data v[2][2];
friend M operator*(M a,M b){
M c;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c.v[i][j]=c.v[i][j]+(a.v[i][k]*b.v[k][j]);
return c;
}
}t[20],a;
int main(){
bin[0]=1;for(int i=1;i<=15;i++)bin[i]=bin[i-1]<<1;
t[0].v[0][0]=t[0].v[0][1]=t[0].v[1][0]=get("1");
for(int i=1;i<=15;i++)
t[i]=t[i-1]*t[i-1];
int T=read();
while(T--){
a.v[0][0]=a.v[1][1]=get("1");
a.v[1][0]=a.v[0][1]=get("0");
scanf("%s",tmp);
int len=strlen(tmp);
ch="";
for(int i=0;i<len;i++)ch+=tmp[i];
if(len==1&&ch[0]=='6'){puts("0");continue;}
n=get(ch)+get("1");
int now=0;
for(int i=15;i>=0;i--){
M tmp=a*t[i];
if(tmp.v[0][0]<=n)
a=tmp,now+=bin[i];
}
printf("%d\n",(now-2)/2);
}
return 0;
}

上一题