【题意分析】
题意:用nnn根火柴棒最多可以摆成几个正方形,不一定要用完火柴棒
首先明确摆法是贴着边一个一个摆下来的,摆法有很多而且都是等价的,我是这么摆的:
那么正方形就是一层一层地摆下来的,那么接下来有两种求法:
每一层比前一层多摆4根火柴,那么根据数列知识:
a1=4,an+1−an=4(n∈N∗)a_1=4,a_{n+1}-a_n=4(n\in \N ^*)a1=4,an+1−an=4(n∈N∗)
⇒Sn=2n2+2n\Rightarrow S_n=2n^2+2n⇒Sn=2n2+2n
或者直接观察:前n层火柴总和就是2∗n∗(n+1)=2n2+2n2*n*(n+1)=2n^2+2n2∗n∗(n+1)=2n2+2n
那么我们需要解出给你的火柴根数最多可以摆出几层。
2n2+2n≥x2n^2+2n\geq x2n2+2n≥x
⇒n≥−2+4+8x4\Rightarrow n\geq\frac{-2+\sqrt{4+8x}}{4}⇒n≥4−2+4+8x
那你floor一下就好了,我们设这个层数为n
求出剩下还有x−(2n2+2n)x-(2n^2+2n)x−(2n2+2n)根火柴
接下来你就分类讨论:因为开始的那个正方形需要3根
接下来一段都是两根一个:
下面这个是三根:
剩下的一段全都是两根一个:
这样就好了,每次询问回答是O(1)O(1)O(1)的
时间复杂度O(T)O(T)O(T)
Code:
#pragma GCC optimize (2)
#pragma GCC optimize ("Ofast")
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#define int long long
using namespace std;
inline int read () {
register int s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
return s * w;
}
signed main () {
int T = read ();
for (register int I = 1; I <= T; ++I) {
int x = read (), layer = floor ((double) ((sqrt (4 + 8 * x) - 2) / 4));
if (x <= 4) {printf ("%d\n", x / 4); continue;}
x -= 2 * layer * layer + 2 * layer; int res = layer * layer;
if (x <= 2) printf ("%lld\n", res);
else if (x <= 3 + (layer - 1) * 2) printf ("%lld\n", res + 1 + (x - 3) / 2);
else if (x < 6 + (layer - 1) * 2) printf ("%lld\n", res + layer);
else if (x == 6 + (layer - 1) * 2) printf ("%lld\n", res + layer + 1);
else printf ("%lld\n", res + (x - 6) / 2 + 2);
}
return 0;
}