F Good Tree (牛客4)

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

Given a tree where all edge weights are 1\textstyle 11, define f(u)=∑vdis(u,v)\textstyle f(u)=\sum_v dis(u,v)f(u)=∑v​dis(u,v), where v\textstyle vv represents all nodes in the tree, and dis(u,v)\textstyle dis(u,v)dis(u,v) is the length of the simple path between node u\textstyle uu and node v\textstyle vv.

A tree is called “good” if there exist two nodes u\textstyle uu and v\textstyle vv such that f(u)−f(v)=x\textstyle f(u)-f(v)=xf(u)−f(v)=x. Given integer x\textstyle xx, determine the minimum number of nodes required for the tree to be “good”.

输入描述:

 

Each test contains multiple test cases. The first line contains the number of test cases t\textstyle tt (1≤t≤105\textstyle 1 \leq t \leq 10^51≤t≤105). The description of the test cases follows.

Each test case contains an integer x(1≤x≤1018)\textstyle x(1\le x\le 10^{18})x(1≤x≤1018), representing the value for which you need to determine the minimum number of nodes required for the tree to be “good”.

输出描述:

 

For each test case, output a single integer, representing the minimum number of nodes required for the tree to be “good”.

It can be shown that the answer always exists.

示例1

输入

复制3 2 3 114514

3
2
3
114514

输出

复制4 5 678

4
5
678

题目意思就是给你一个点 u 在一颗树里f(u)=∑v​dis(u,v)的公式,算两个点之间函数f(a)-f(b)=x的最少点数,我们先选定确定一条链的长度,确定链的两个端点。发现我们有奇数个点(2*k+1)的时候可以使f(a)-f(b)最大长度为k*k.(因为最大必须在链的两端加点)。之后我们反过来想,从长度k回推点数,会得到一段区间:

我们从区间考虑,显而易见在(k+1)*(k+1)处的点为2*k+3,我们接下来考虑在这3个长度之间所需要的点的数量。在图中右区间的距离都可以用2*k+3个点构造出来,而左区间不一定只用2*k+2个点就可以构造出来。有一部分需要用2*k+3构造出来。如果你在左区间中如果点数与长度同余相等就加2,否则就加3.

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define endl "\n"
int t,n;
signed main() {
	IOS
	cin>>t;
	while(t--) {
		cin>>n;
		int sq=(long long)sqrtl(n);
		if(n==sq*sq)cout<<2*sq+1<<endl;
		else if(n==sq*(sq+1))cout<<2*sq+2<<endl;
		else if(n>sq*(sq+1))cout<<2*sq+3<<endl;
		else{
			if((n-sq*sq)%2==(sq%2)){
				cout<<sq*2+2<<endl;
			}else{
				cout<<2*sq+3<<endl;
			}
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值