链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
“开导!”
众所周知,树是一种特殊的图。
众所周知(二),导出子图是由该图顶点的一个子集和该图中两端均在该子集的所有边的集合组成的图。
注1:二叉树是有向图。
注2:有向图的导出子图,还是有向图。
小沙有 nnn 个节点,他需要你构造出一颗有根二叉树,使得二叉树的所有导出子图是一颗满二叉树的数目尽可能多。
请问构造出来的有根二叉树的所有导出子图是一颗满二叉树的数目最多是多少?
你能帮帮不会数/树的小沙吗?
输入描述:
第一行读入一个整数 TTT ,代表多组样例。
随后 TTT 行,每行输入一个正整数 nnn。
保证有 1≤T≤1051 \le T \le 10^51≤T≤105,1≤n≤10181 \le n \le 10^{18}1≤n≤1018。
输出描述:
对于每组样例输出一行整数代表答案。
由于答案过大,所以请输出答案对 109+710^9 + 7109+7 取模的值。
示例1
输入
复制10 1 2 3 4 5 6 7 8 9 10
10 1 2 3 4 5 6 7 8 9 10
输出
复制1 2 4 5 7 8 11 12 14 15
1 2 4 5 7 8 11 12 14 15
思路:
对于n个点,我们分两部分计算,第一部分是当前所能达到的最大满树,一部分是多余的点。
对于第一部分:它的大小呈2*n的递增;
对于第二部分:他们每个点都会贡献一次,每两个点又会贡献一次.......。(这部分看代码吧)
代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
const int N =1e6+1000;
const long long MX = 1e9 + 7;
int t;
long long n,ans=0;
int main()
{
cin >> t;
while (t--)
{
cin >> n;
long long x = 1,p=1;
while (x < n)
{
ans += x;
ans = ans % MX;
p *= 2;
x += p;
}
x = x / 2;
n = n - x;
while (n)
{
ans += n;
n /= 2;
ans = ans % MX;
}
cout << ans << endl;
ans = 0;
}
return 0;
}