链接:登录—专业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)=∑vdis(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)=∑vdis(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;
}