noip模拟赛 块

【问题描述】

拼图达人小C手里有n1*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);
	}
}
原文地址:https://www.cnblogs.com/qwerfcxs/p/7802346.html