做题感悟:这种题以前做过类似的题,但是在做这题时一直超内存,真心无语,后来才发现开一个数组就 ok了我傻傻的开了两个怪不得呢 ! 做完之后百度了一下原来还有更简单的方法不用开数组就可以了。
解题思路:1 ) 开数组。可以先打个表,把到前 i 个的和存到 f [ i ] 中,这样就可以用二分查找到 s 处于第几堆,然后再用一次二分查找在第几层。
2 ) 不开数组。 a1 =1, a2 = 3 , a3 = 6 , so ~ > an = (1+ n) * n / 2 ; 于是前 n 项和 Sn = a1+a2+a3……an = 1/2 *( 1*1+1 + 2*2 +2 +3*3+3 ……i * i + i ……n * n + n ) =
1/2 * ( 1^2 +2^2+3^2 …… i ^ 2 +n^2 + 1+2+3+4+5+……+ i + ……n ) = 1/2*( ∑n*n + ∑n ) = n*(n+1)*(n+2)/6 ;
公式:前n项和公式 = n * ( n + 1 ) / 2 ; 平方和公式:n * ( n+1 ) * ( 2*n+1 ) / 2 ; 立方和公式 :[ n * ( n+1 ) / 2 ] ^ 2 ;
代码:
#include<stdio.h>
#include<iostream>
#include<map>
#include<stack>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std ;
#define LEN sizeof(struct node)
#define pret(a,b) memset(a,b,sizeof(a))
#define lld __int64
const double PI = 3.1415926535898 ;
const int INF = 99999999 ;
const double esp = 1e-7 ;// 精确到 7 位即可,8位超时
const lld md= 2810778 ;
const int MX = md+5 ;
lld binary_searchA(lld n)
{
lld le=0,rt=md,mid,fx ;
while(le<rt)
{
mid=(le+rt)/2 ;
fx=mid*(mid+1)*(mid+2)/6 ;
if(fx==n) return mid ;
else if(fx>n) rt=mid ;
else le=mid+1 ;
}
return le ;
}
lld binary_searchB(lld n)
{
lld le=0,rt=md,mid,fx ;
while(le<rt)
{
mid=(le+rt)/2 ;
fx=mid*(mid+1)/2 ;
if(fx==n) return mid ;
else if(fx>n) rt=mid ;
else le=mid+1 ;
}
return le ;
}
int main()
{
lld Tx,n,y,cx ;
scanf("%I64d",&Tx) ;
while(Tx--)
{
scanf("%I64d",&n) ;
lld ax=binary_searchA(n) ; // 在第几堆
if(ax*(ax+1)*(ax+2)/6==n)
y=ax*(ax+1)/2 ;
else
y=n-(ax-1)*ax*(ax+1)/6 ;
lld bx=binary_searchB(y) ; // 第几层
if(bx*(bx+1)/2==y)
cx=bx ;
else
cx=y-(bx-1)*bx/2 ;
printf("%I64d %I64d %I64d\n",ax,bx,cx) ;
}
return 0 ;
}
代码(开数组):
#include<stdio.h>
#include<iostream>
#include<map>
#include<stack>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std ;
#define LEN sizeof(struct node)
#define pret(a,b) memset(a,b,sizeof(a))
#define lld __int64
const double PI = 3.1415926535898 ;
const int INF = 99999999 ;
const double esp = 1e-7 ;
const lld md= 2810778 ;
const int MX = md+5 ;
lld f[MX] ;
void init() // 打表
{
lld p=2 ; f[1]=1 ; f[0]=0 ;
for(int i=2 ;i<=md ;i++)
f[i]=f[i-1]+p++ ;
for(int i=1 ;i<=md ;i++)
f[i]+=f[i-1] ;
}
lld binary_search(lld le,lld rt,lld n)
{
lld mid ;
while(le<rt)
{
mid=(rt+le)/2 ;
mid*(mid+1)/2 > n ? rt=mid : le=mid+1 ;
}
return le ;
}
int main()
{
init() ;
int Tx ;
lld n,a,b,c,bx ;
scanf("%d",&Tx) ;
while(Tx--)
{
scanf("%I64d",&n) ;
lld x,y ;
x=lower_bound(f,f+md,n)-f ;
if(f[x]>n)
x-- ;
if(f[x]==n) // 判断在第几堆
a=x ;
else a=x+1 ;
y=n-f[x] ;
if(!y) y=f[x]-f[x-1] ; // 算出第几个数
b=binary_search(0,md,y) ; // 计算第几层 b*(b+1) >=y ;
if(b*(b+1)/2==y)
bx=b ;
else if(b*(b+1)/2>y) // 计算第几层
{
b-- ;
if(b*(b+1)/2==y)
bx=b ;
else
bx=b+1 ;
}
c=y-bx*(bx-1)/2 ;
printf("%I64d %I64d %I64d\n",a,bx,c) ;
}
return 0 ;
}