数学公式: n^2的前n项和n(n+1)(2*n+1)/6,用二分进行查找;
算出层数后继续二分查找位于这一层的哪一位,也可以推出相应公式
#include#include #include #include 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\n",ti++,(ll)(floor-1)*(floor-1)+index); } return 0;}