Codeforces | CF1029F 【Multicolored Markers】

这道题其实难度应该小于紫题...除了一点小特判以外没什么难度...\(\leq50\)行代码即可\(AC\)此题
题目大意:给定两个数\(a,b(1\leq a,b\leq 10^{14})\)分别表示红色方格个数和蓝色方格个数,求这\(a\)个红色方格和\(b\)个蓝色方格构成的矩形周长的最小值,且满足在所构成的矩形中至少有一种颜色的所有方块也能构成一个矩形,数据保证存在至少一种合法的染色方案.
这道题本质是数学题,根据矩形周长一定时长与宽的差越小矩形面积越大可以反推出矩形面积一定时长与宽的差越小矩形周长越小,所以我们可以从\(\lfloor\sqrt{a+b}\rfloor\)\(1\)枚举所构成的大矩形的宽,这样可以保证有合法解即为最优解,不需要再考虑后面其他的合法解.
对于一个合法的大矩形,设其宽为\(i\),长为\(d\),应当满足\(a+b==i\times d\),且对于\(a\)\(b\)中至少一个数存在一种因数分解方案\(e\times f(e\leq f)\)满足\(e\leq i\)\(f\leq d\)(即当红色或蓝色方块构成矩形时能够被大矩形所包含),对此我们只需要对\(i\)做一次\(O(\lfloor\sqrt{a+b}\rfloor)\)的枚举.检验时只需对\(a\)\(b\)\(O(i)\)的枚举即可(当枚举的宽\(>i\)时显然已经不合法故只需枚举\(\leq i\)的宽).
下面例行放\(AC\)代码\(\downarrow\downarrow\downarrow\)

#include<cstdio>//CF1029F
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdlib>

using namespace std;

long long a,b,c,d;

bool check(int u,long long v){
	for(int i=1;i<=u;i++){
		if(a%i==0){
			long long rep=a/i;
			if(i<=u&&rep<=v){
				return true;
			}
		}
	}
	for(int i=1;i<=u;i++){
		if(b%i==0){
			long long rep=b/i;
			if(i<=u&&rep<=v){
				return true;
			}
		}
	}
	return false;
}

int main(){
	scanf("%lld%lld",&a,&b);
	c=a+b;
	for(int i=(int)sqrt(c);i;i--){
		if(c%i==0){
			d=c/i;
			if(check(i,d)){
				printf("%lld",(d+i)*2);
				return 0;
			}
		}
	}
	return 0;
}
posted @ 2018-09-05 07:37  __BLUESKY007  阅读(240)  评论(0编辑  收藏  举报