1. 问题描述:
现在,我们要在平面上画出 n 个边长为 1 的正方形。注意,这 n 个正方形之间允许存在公共边。每个正方形的所有端点坐标都必须为整数,且所有边都必须平行于坐标轴。我们将逐边绘制整个图形。当绘制某一条边时,如果该边的两端端点为 (x,y) 和 (x,y + 1),而我们在之前已经绘制了一条端点为 (x′,y) 和 (x′,y + 1) 的边,则该边可以利用之前绘制的边作为参考,迅速画出。同样的,如果即将绘制的边的两端端点为 (x,y) 和 (x + 1,y),而我们在之前已经绘制了一条端点为 (x,y′) 和 (x + 1,y′) 的边,则该边也可以利用之前绘制的边作为参考,迅速画出。但是,如果即将绘制的边不满足上述条件,也就是不具备参考边,则为了保证绘图精确,我们需要借助尺子来绘制该条边。如,当 n = 1 时,我们首先需要借助尺子绘制两条边,如下:
然后,借助以上两边完成剩余两边的绘制:
当 n = 2 时,我们首先需要借助尺子绘制三条边,如下:
然后,借助以上三边完成剩余所有边的绘制:
我们希望在画出 n 个边长为 1 的小正方形的同时,借助尺子绘制的边的数量尽可能少。请问,最少需要用尺子画多少条边。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。每组数据占一行,包含一个整数 n。
输出格式
每组数据输出一行结果,表示需要用尺子绘制的最少边数。
数据范围
1 ≤ T ≤ 10,
1 ≤ n ≤ 10 ^ 9
输入样例:
3
1
2
4
输出样例:
2
3
4
来源:https://www.acwing.com/problem/content/3811/
2. 思路分析:
我们其实可以抽象一下题目可以发现实际上是需要求解出边长分别为a和b满足ab >= n的条件下a + b的最小值,因为a和b是对称的所以假设a <= b,当a确定之后那么b也一定是确定为⌈n / a⌉,所以我们可以枚举所有的a,只需要枚举到⌈n / a⌉即可,时间复杂度为O(√n)所以是可以通过的;其实我们还可以使用到一个性质:两个数字的积确定的时候,两个数字的差越小那么他们的和也是越小的,所以要想使得a + b越小那么需要使得a与b的差越小,而ab >= n所以a和b尽可能相等也即靠近√n,这样得到的a + b一定是最小的。
3. 代码如下:
枚举:
class Solution:
def process(self):
T = int(input())
for i in range(T):
n = int(input())
res = n + 1
# 枚举a, 得到满足ab >= n的时候a + b最小
a = 1
while a <= (n + a - 1) // a:
# b = (n + a - a) // a, 为n / a向上取整转化为向下取整的等式
res = min(res, a + (n + a - 1) // a)
a += 1
print(res)
if __name__ == '__main__':
Solution().process()
性质:两个数字的积一定的时候,差越小那么和越小:
import math
class Solution:
def process(self):
T = int(input())
for i in range(T):
n = int(input())
a = int(math.sqrt(n))
b = (n + a - 1) // a
print(a + b)
if __name__ == '__main__':
Solution().process()