Codeforces 466B Wonder Room【思维+暴力枚举】直觉题

解决N个学生在给定a*b尺寸房间中的最优住宿分配方案,确保每个学生拥有至少6平方米的空间,同时使房间总面积尽可能小。

B. Wonder Room
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The start of the new academic year brought about the problem of accommodation students into dormitories. One of such dormitories has a a × b square meter wonder room. The caretaker wants to accommodate exactly n students there. But the law says that there must be at least 6 square meters per student in a room (that is, the room for n students must have the area of at least 6n square meters). The caretaker can enlarge any (possibly both) side of the room by an arbitrary positive integer of meters. Help him change the room so as all n students could live in it and the total area of the room was as small as possible.

Input

The first line contains three space-separated integers n, a and b (1 ≤ n, a, b ≤ 109) — the number of students and the sizes of the room.

Output

Print three integers s, a1 and b1 (a ≤ a1b ≤ b1) — the final area of the room and its sizes. If there are multiple optimal solutions, print any of them.

Examples
Input
3 3 5
Output
18
3 6
Input
2 4 4
Output
16
4 4

题目大意:


一共有N个学生需要分配住宿,现在给你一个a*b的场地,为这N个学生分配空间。

规定每个学生至少要有6平方米的空间,形状必须是矩形。

如果我们给出的场地不能给这N个学生分配空间,那么我们可以通过增大a,b的值来得到更多的空间去分配。

问最终的场地最小面积是多少,其长和宽分别是多少(有spj);


思路:


1、考虑这样一点,如果原场地a*b<n*6,那么肯定场地大小是不够的,我们需要去扩张。

如果a*b>=n,通过脑补和简单分析,不难得到结论,这样的情况,是一定够分配空间的。


2、那么我们任务就是对于a*b<n*6的情况进行处理,使得:(a+i)*(b+j)>=n,并且最终解使得(a+i)*(b+j)尽可能的小。

那么我们分成两种情况去讨论:

①n可以拆分成ans1*ans2==n的形式,并且右ans1>=a&&ans2>=b,那么就存在一种分配方式,使得不浪费空间的情况下,就解决了该问题,显然最优。

②如果n不能拆分成ans1*ans2==n的形式.那么我们考虑暴力枚举i,通过简单分析可知,i约为1e7即可。那么此种情况我们暴力枚举过程中,求出j的最小值,然后过程维护一个最小乘积即可。


3、这类题做起来很玄学,但是其实这类题很套路,更多是需要靠直觉来猜出暴力做法,想要快速得出证明,窝还是差很多的。



Ac代码:

#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define ll __int64
int main()
{
    ll n,a,b;
    while(~scanf("%I64d%I64d%I64d",&n,&a,&b))
    {
        if(n*6<=a*b)
        {
            printf("%I64d\n%I64d %I64d\n",a*b,a,b);
        }
        else
        {
            int flag=0;
            n*=6;
            for(ll i=1;i<=sqrt(n);i++)
            {
                if(n%i==0)
                {
                    ll ans1=i;
                    ll ans2=n/i;
                    if(ans1>=a&&ans2>=b)
                    {
                        flag=1;
                        printf("%I64d\n%I64d %I64d\n",n,ans1,ans2);
                        break;
                    }
                    else if(ans1>=b&&ans2>=a)
                    {
                        flag=1;
                        printf("%I64d\n%I64d %I64d\n",n,ans2,ans1);
                        break;
                    }
                }
            }
            if(flag==0)
            {
                ll output1=0;
                ll output2=0;
                ll minn=1000000000000000000;
                for(ll i=0;i<=20000000;i++)
                {
                    ll ans1=a+i;
                    if(ans1*b>=n)
                    {
                        if(ans1*b<=minn)
                        {
                            minn=ans1*b;
                            output1=ans1;
                            output2=b;
                        }
                    }
                    else
                    {
                        ll need=n-ans1*b;
                        ll up=need/ans1;
                        if(need%ans1!=0)up++;
                        ll ans2=b+up;
                        if(ans1*ans2>=n)
                        {
                            if(ans1*ans2<=minn)
                            {
                                minn=ans1*ans2;
                                output1=ans1;
                                output2=ans2;
                            }
                        }
                    }
                }
                printf("%I64d\n%I64d %I64d\n",minn,output1,output2);
            }
        }
    }
}












评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值