【题意分析】
题意:用 n n n根火柴棒最多可以摆成几个正方形,不一定要用完火柴棒
首先明确摆法是贴着边一个一个摆下来的,摆法有很多而且都是等价的,我是这么摆的:
那么正方形就是一层一层地摆下来的,那么接下来有两种求法:
每一层比前一层多摆4根火柴,那么根据数列知识:
a 1 = 4 , a n + 1 − a n = 4 ( n ∈ N ∗ ) a_1=4,a_{n+1}-a_n=4(n\in \N ^*) a1=4,an+1−an=4(n∈N∗)
⇒ S n = 2 n 2 + 2 n \Rightarrow S_n=2n^2+2n ⇒Sn=2n2+2n
或者直接观察:前n层火柴总和就是 2 ∗ n ∗ ( n + 1 ) = 2 n 2 + 2 n 2*n*(n+1)=2n^2+2n 2∗n∗(n+1)=2n2+2n
那么我们需要解出给你的火柴根数最多可以摆出几层。
2 n 2 + 2 n ≥ x 2n^2+2n\geq x 2n2+2n≥x
⇒ n ≥ − 2 + 4 + 8 x 4 \Rightarrow n\geq\frac{-2+\sqrt{4+8x}}{4} ⇒n≥4−2+4+8x
那你floor一下就好了,我们设这个层数为n
求出剩下还有 x − ( 2 n 2 + 2 n ) 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;
}