今天上午终于把最后一题D题水掉了。我的二分也算是AK了了吧。
这题可以说我还是有版权的,嘿嘿~~越来越有意思了!
说一下怎么做吧。
听说有公式就试着自己推了一下,感觉不错呢。
首先我们可以看出
a1=1,a2=3,a3=6. 很显而易见的an=(1+n)*n/2;
那么Sn怎么求呢???Sn=∑an=(1/2)∑(n*n+n)=0.5*(∑n*n+∑n);
这样就转化为连续自然数平方的和与连续自然数的和了。
连续自然数和:(1+n)*n/2
平方的和公式:n(n+1)(2n+1)/2
立方的和公式:[n(n+1)/2]^2
将公式带入最终化简------>Sn=n(n+1)(n+2)/6; 很漂亮的一个公式诞生了
接下来用二分来搜索答案就好了。
觉得自己的代码还是很美观的~虽然还有漏洞
#include<iostream>
#define MAXLayer 1111111
using namespace std;__int64 layerSum[MAXLayer];__int64 getSum( __int64 m )
{__int64 sum;sum=m*(m+1)/2;if( sum%3==0 ){sum/=3;sum*=(m+2);}else sum*=(m+2)/3;return sum;
}int BinarySeachLayer( __int64 &num )
{__int64 l=1,r=3810776,m;__int64 sum;while( m=(l+r)/2,l<r ){sum=getSum(m);if( sum>=num ) r=m;else l=m+1;}num-=getSum(m-1);return (int)m;
}int BinarySeachRow( __int64 &num )
{__int64 l=1,r=3810776,m;__int64 sum;while( m=(l+r)/2,l<r ){sum=(1+m)*m/2;if( sum>=num ) r=m;else l=m+1;}num-=(m-1)*m/2;return (int)m;
}
int main()
{__int64 N;int T;scanf( "%d",&T );while( T-- ){ scanf("%I64d",&N);int Layer=BinarySeachLayer( N );int Row=BinarySeachRow( N );int Column=N;printf( "%d %d %d\n",Layer,Row,Column );}return 0;
}