数学公式: n^2的前n项和n(n+1)(2*n+1)/6,用二分进行查找;
算出层数后继续二分查找位于这一层的哪一位,也可以推出相应公式
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll f(ll n) //a(n)=n^2的前n项和公式 { return n*(n+1)*(2*n+1)/6; } ll f2(ll i,ll n) //这个公式要推一下 { if(i<=n) return i*(i+1)/2; return n*n-(2*n-i)*(2*n-i-1)/2; } int main() { freopen("army.in","r",stdin); int t; scanf("%d",&t); int ti=1; while(t--) { ll n; scanf("%I64d",&n); int lef=1,rig=1500000,floor; while(1) //二分算哪一层 { floor=(lef+rig)/2; if(n>f(floor-1) && n<=f(floor)) break; if(n<=f(floor)) rig=floor-1; else lef=floor+1; } ll tmp=f(floor-1); lef=1; rig=2*floor-1; int index; while(1) //二分算这一层的哪一个 { index=(lef+rig)/2; if(n>tmp+f2(index-1,floor) && n<=tmp+f2(index,floor)) break; if(n<=tmp+f2(index,floor)) rig=index-1; else lef=index+1; } printf("Case %d: %I64d ",ti++,(ll)(floor-1)*(floor-1)+index); } return 0; }