题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2446

2 19 75822050528572544
4 4 3 769099 111570 11179
题意:
叠金字塔,最顶层数量是1,第二层数量是3,之后每一层的数量都是上面一层的数量加当前层数的值啦。一层金字塔有1个球,两层金字塔有1+3 = 4个球,三层金字塔就有1+3+6 = 10个的球。
现在给出一个编号s,问它在金字塔中的第几层,第几行,第几列。
例如19,在第四层,第四行,第三列。
PS:
首先打表出每一座金字塔的数量, 和第n座金字塔的编号(也就是前n座金字塔共有的数量);
然后先二分查找出给出的编号所在的金字塔,然后再一次二分找出给出的编号在当前金字塔的哪一行哪一列!
代码如下:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef __int64 LL;
#define N 2000017
LL p[N] = {0}, sn[N] = {0};
//a每一个位置的数,b:Sn
LL findd1(LL n)
{
LL s = 1, e = N, mid;
while(s < e)
{
mid = (s+e)/2;
if(sn[mid] < n)
s = mid+1;
else if(sn[mid] > n)
e = mid-1;
else
return mid;
}
return s;
}
LL findd2(LL n, LL endd)
{
LL s = 1, e = endd, mid;
while(s < e)
{
mid = (s+e)/2;
if(p[mid] < n)
s = mid+1;
else if(p[mid] > n)
e = mid-1;
else
return mid;
}
return s;
}
int main()
{
LL t;
LL n;
memset(p,0,sizeof(p));
memset(sn,0,sizeof(sn));
for(int i = 1; i < N; i++)//每一堆
{
p[i] = p[i-1]+i;
}
for(int i = 1; i < N; i++)//Sn
{
sn[i] = p[i]+sn[i-1];
}
/* for(int i = N-10; i < N; i++)
{
printf("%I64d\n",sn[i]);
}*/
//2^63 = 9223372036854775808
scanf("%I64d",&t);
while(t--)
{
scanf("%I64d",&n);
LL weizhi = findd1(n);
// printf("pos:%I64d\n",weizhi);
if(sn[weizhi] < n)
weizhi+=1;
LL tt = n-sn[weizhi-1];//本堆的个数
LL r = findd2(tt,weizhi);
//printf("R:%I64d\n",r);
if(p[r] == tt)
{
printf("%I64d %I64d %I64d\n",weizhi,r,r);
}
else
{
if(p[r] < tt)
r++;
LL c = tt - p[r-1];
printf("%I64d %I64d %I64d\n",weizhi,r,c);
}
/*else
{
LL c = tt - p[r-1];
printf("%I64d %I64d %I64d\n",weizhi,r,c);
}*/
}
return 0;
}
/*
2
14
15
*/
HDU 2446 Shell Pyramid(二分查找 数学)
原文地址:http://blog.csdn.net/u012860063/article/details/39805335