F. Multicolored Markers 暴力+二分

F. Multicolored Markers

题目大意:

给你 a个红块 b个蓝块 拼成一个实心矩形,并且要求红块或者蓝块自成一个矩形,问形成的这个矩形最小的周长是多少。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <bitset>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
vector<pair<ll,ll>>G[3];
ll a,b;
 
void init(){
    ll sum=a+b;
    for(ll i=1;i*i<=sum;i++){
        if(sum%i==0){
            G[0].push_back(make_pair(i,sum/i));
        }
    }
    for(ll i=1;i*i<=a;i++){
        if(a%i==0){
            G[1].push_back(make_pair(i,a/i));
        }
    }
    for(ll i=1;i*i<=b;i++){
        if(b%i==0){
            G[2].push_back(make_pair(i,b/i));
        }
    }
}
 
bool check(int num,int u,ll x){
    if(G[num][u].first<=x) return true;
    return false;
}
 
int main(){
    scanf("%lld%lld",&a,&b);
    init();
    ll ans=inf64;
    for(int i=0;i<G[0].size();i++){
        ll len=G[0][i].first;
        int l=0,r=G[1].size()-1,res=-1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(1,mid,len)) l=mid+1,res=mid;
            else r=mid-1;
        }
        if(res!=-1&&G[0][i].second>=G[1][res].second) ans=min(ans,2*(G[0][i].first+G[0][i].second));
    }
    for(int i=0;i<G[0].size();i++){
        ll len=G[0][i].first;
        int l=0,r=G[2].size()-1,res=-1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(2,mid,len)) l=mid+1,res=mid;
            else r=mid-1;
        }
        if(res!=-1&&G[0][i].second>=G[2][res].second) ans=min(ans,2*(G[0][i].first+G[0][i].second));
    }
    printf("%lld
",ans);
    return 0;
}
 
View Code
原文地址:https://www.cnblogs.com/EchoZQN/p/11644545.html