您的位置:首页 > 其它

2017年浙江中医药大学大学生程序设计竞赛(重现赛)B - 一生之敌

2017-12-21 14:58 225 查看

题目描述

大家都知道Alice和Bob两个人是一生之敌。(雾
但某天,他们两个人发了疯。想知道他们两个是否可以成为朋友。
于是他们做了一个令人窒息的决定。
Alice和Bob每个人任意选一个整数。
假设Alice选择了整数a,Bob选择了整数b。
Alice使得a做如下变换:
a -> 2 * a * (a+1)^2
Bob使得b做如下变换:
b -> b^2
如果变换后的数字相等,则两个人可以化敌为友。
如果不相等,这两个人怕是石乐志。
现在,你想把Bob部分可能的整数b(存在a变换后的数字等于b变换后的数字)从小到大排列后,知道第一个大于等于n的数字是多少。

输入描述:

第一行输入一个整数T,表示数据组数。
每组数据输入一个整数n。
1 <= T <= 100000
0 <= n <= 10^19
保证结果存在

输出描述:

输出一个整数。


示例1

输入

3
2
6
100


输出

6
6
114

题解

二分查找。

要使得$ b^2 = 2 * a * (a+1)^2$,即$b= \sqrt{2 * a * (a+1)^2}$。

因为$b$是整数,所以`$\sqrt{2 * a * (a+1)^2}$`也是整数,因此$\sqrt{2 * a}$为整数。

设$p$为整数,则$a$可以表示为$a = 2*p*p$,则$b = 2*p*(2*p*p+1)$,因此二分$p$就可以得到答案了。

最后注意一下溢出的问题。

#include <bits/stdc++.h>
using namespace std;

int T;

int main() {
scanf("%d", &T);
while(T --) {
unsigned long long n;
scanf("%llu", &n);
if(n == 0) {
printf("0\n");
continue;
}
unsigned long long L = 0;
unsigned long long R = 3e6;
unsigned long long ans;
while(L <= R) {
unsigned long long mid = (L + R) / 2;
unsigned long long p = mid * mid * mid * 4LL + mid * 2LL;
if(p >= n) {
ans = p;
R = mid - 1;
} else {
L = mid + 1;
}
}
printf("%llu\n", ans);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐