一起又看流星雨
总提交:118 测试通过:34
描述
《一起又看流星雨》相信大家都看过这部电视剧吧。青叶竹在暑假的时候也很着迷这部电视剧!!!有一天,楚雨荨想知道云海到底爱她有多深,于是,她决定考验一下云海的毅力。楚雨荨在班级的学习几乎每次都第一,她出的问题可不简单哦~问题描述如下:
给出一排金字塔的规律如下:
每个球的编号从左至右,从上到下,编号依次为: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
http://blog.csdn.net/songjs19931206/article/details/43017763
·先看一下基本的二分用法。
分析:
·两次二分查找答案:分别得出堆号、行号,再减一下就是列号。
(其中前n堆、前n行都有计算公式,可以快速求出,这也是使用二分计算当前结果的重要依据)
Code:
#include<stdio.h>
#include <cmath>
#include<math.h>
__int64 f[900000];
__int64 binarysearch(__int64 n)
{
__int64 l, r, mid;
l = 0;
r = 899999;
while (l < r)
{
mid = (l + r) / 2;
if ((l + r) % 2)
mid += 1;
if (f[mid] < n)
l = mid;
else
r = mid - 1; //????????
}
return l;
}
int main()
{
__int64 T,i,j,k,t,n,m,num,zu,hang,lie;
num=0;t=1;n=1;
for(i=0;i<900000;i++)
{
if(t)
{
num=num+(1+n)/2*n;
t=0;
}
else
{
num=num+n/2*(n+1);
t=1;
}
f[n]=num;
n++;
}
scanf("%I64d",&T);
while(T--)
{
zu=hang=lie=0;
scanf("%I64d",&n);
zu= binarysearch(n);
zu++;
n=n-f[zu-1];
hang=(int)floor((sqrt(8.0*n+1)-1)/2-1e-9)+1;
hang--;
lie=n-(hang+1)*hang/2;
printf("%I64d %I64d %I64d\n",zu,hang+1,lie);
}
return 0;
}