题目链接: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