【问题描述】
拼图达人小C手里有n个1*1的正方形方块,他希望把这些方
块拼在一起,使得拼出的图形周长最小,要求方块不能重叠。擅长拼
图的小C一下就求出了这个周长,顺便他想考考你会不会求。
【输入格式】
多组数据,第一行一个正整数T,表示数据组数。
接下来T行,每行一个正整数n,表示方块数。
【输出格式】
输出T行,每行一个正整数,表示答案。
【样例输入】
3
4
11
22
【样例输出】
8
14
20
【数据范围】
对于20%的数据,n<=20;
对于40%的数据,n<=1000;
对于60%的数据,n<=10^6;
对于80%的数据,n<=10^10;
对于100%的数据,n<=10^12,T<=10。
【题解】
很显然,拼出来的东西轮廓线可以变换为一个长方形
正解是拼成正方形,再把剩下的补在周围,乱搞一下就好了。
可是这样很容易写挂
于是,可以暴力的从√n往大和往小搜一个范围枚举长方形一条边长,然后取个最小值就好了
【代码】
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
#define f(i,n) for(int i=1;i<=(n);i++)
#define ll long long
#define INF 1ll<<50
#define N 500000
#define c 32123
int main()
{
freopen("block.in","r",stdin);
freopen("block.out","w",stdout);
int t;
scanf("%d",&t);
ll n;
while(t--)
{
scanf("%lld",&n);
ll s=sqrt(n);
ll s1=max(1ll,s-500000),s2=min(n,s+500000);
ll ans=INF;
for(ll i=s1;i<=s2;i++)
{
if(n%i==0)ans=min(ans,2*(i+n/i));
else ans=min(ans,2*(i+n/i+1));
}
printf("%lld\n",ans);
}
}