您的位置:首页 > 其它

bjfuOJ 1086 一起又看流星雨(公式+二分)

2015-01-30 13:03 169 查看


一起又看流星雨

时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte

总提交:179 测试通过:65

描述

《一起又看流星雨》相信大家都看过这部电视剧吧。青叶竹在暑假的时候也很着迷这部电视剧!!!有一天,楚雨荨想知道云海到底爱她有多深,于是,她决定考验一下云海的毅力。楚雨荨在班级的学习几乎每次都第一,她出的问题可不简单哦~问题描述如下:

给出一排金字塔的规律如下:



每个球的编号从左至右,从上到下,编号依次为:1,2,3,4,5…..。

给你一个编号数n,你能不能快速算出它在第几堆,第几行,第几列。例如:给你一个编号数n=3,我们能迅速算出它在的堆号i=2,行号j=2,列号k=1。给你一个编号19,我们能迅速算出它在的堆号i=4,行号j=4,列号k=3。但是,如果给你一个编号数n= 2^60,你能否快速的算出来呢。于是,云海请求聪明的你帮他写一个程序解决这个问题。

输入

输入第一行为一个整数t,表示测试数据组数。

有多组测试数据(不超过20组),每组一行,每行有一个正整数n(0<n<=2^60)表示球的编号。

输出

对于每个球的编号n,输出它所在的堆号i,行号j,列号k,两个数之间用一个空格隔开.

样例输入
3

3

19

75822050528572544

样例输出
2 2 1

4 4 3

769099 111570 11179

·写了两个二分函数:计算当前堆,与当前行。

LL binary01(LL n){
LL left,right;
left = 1;right = 1<<20;
while(left <= right){
LL mid = (left+right)/2;
//        printf("mid:  %lld\n",mid);
if(mid*(mid+1)*(mid+2)/6 == n){
return mid;
}else if(mid*(mid+1)*(mid+2)/6 > n){
right = mid-1;
}else left = mid+1;
}
return left;
}
LL binary02(LL n){
LL left,right;
left = 1;right = 1<<30;
while(left <= right){
LL mid = (left+right)/2;
if(mid*(mid+1)/2 == n){
return mid;
}else if(mid*(mid+1)/2 > n){
right = mid-1;
}else left = mid+1;
}
return left;
}
int main(){
int t;scanf("%d",&t);
while(t--){
LL n;
scanf("%lld",&n);
LL k = binary01(n);
printf("%lld",k);k--;
n = n - k*(k+1)*(k+2)/6;
k = binary02(n);
printf(" %lld",k);k--;
printf(" %lld\n",n-(k+1)*k/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: