NC20650 可爱の星空
题目
题目描述
“当你看向她时,有细碎星辰落入你的眼睛,真好。”——小可爱
在一个繁星闪烁的夜晚,卿念和清宇一起躺在郊外的草地上,仰望星空。
星语心愿,他们,想把这片星空的星星,连成一棵漂亮的树,将这美好的景色记录下来。
现在,天上共有n颗星星,编号分别为1,2.....n,一开始任何两个点之间都没有边连接。
之后,他们两个想在在(u,v)之间连无向边,需要付出|u联通块大小-v联通块大小|的代价。
他们两个想用最少的代价来使这n个点联通,所以他们想知道最小代价是多少。
(多组数据
输入描述
第一行一个正整数,表示数据组数T
接下来T行每行一个正整数,表示询问的n
输出描述
T行,每行一个数表示答案
示例1
输入
1 5
输出
2
说明
1,2....5五个点,连边顺序为(1,2),(3,4),(1,5),(5,3),代价为0,0,1,1,总代价为2,是n=5的时候最优答案。
虽然(1,2),(2,3),(3,4),(4,5)也可以,但是代价为0,1,2,3,总代价为6,比2大。
备注
对于20%的数据,T<=2,n<=10
对于40%的数据,T<=10,n<=1000
对于60%的数据,T<=100000,n<=100000
对于另外40%的数据,T=1,n<=1000000000000
题解
知识点:递归。
一个贪心结论,合并成大小为 的连通子图时应选两个大小最接近的连通子图,也就是各自占一半 。因此偶数时候应当是两个 ,奇数时候应当是 和 。
因此,数据小可以通过记忆化搜索递归求解,但这里数据很大,没法记忆化。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; ll f(ll x) { if (x == 1 || x == 2) return 0; if (x & 1) return f(x / 2) + f(x / 2 + 1) + 1; else return 2 * f(x / 2); } bool solve() { ll n; cin >> n; cout << f(n) << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16570696.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧