列表

详情


NC19955. [FJOI2015]世界树

描述

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

输入描述

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

输出描述

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

示例1

输入:

2
5
12345

输出:

1
9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

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;
}

上一题