Codeforces Round #791 (Div. 2) A - AvtoBus(暴力 贪心 数学)

题目来源

A AvtoBus

点此进入题面

题意:
给定一个数 n,如果它能被 m46 组合而成,输出 m 的最小值和最大值。

如果不能被若干 46 组成,输出 -1。

思路:

首先,当 n 为奇数 或 n 小于 4 的时候,显然是不能被 46 组合而成的,这需要进行特判。

具体思路见代码注释。

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")

#include<bits/stdc++.h>

using namespace std;

#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef map<int, int> mi;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
#define pb push_back
#define pp pop_back
#define x first
#define y second
const int N = 2e5 + 10;

signed main()
{
    int T = 1;
    cin>>T;

    while (T--)
    {
        int n; cin >> n;
        if (n < 4 || n & 1)
        {
            puts("-1");
            continue;
        }

        int mn, mx;
        if (n % 4 == 0)		//能被 4 整除的话
        {
            mx = n / 4;		//显然 n / 4  max
            if (n % 6 == 0)		//如同时可以被 6 整除
            {
                mn = n / 6;		//那么n / 6  min
                cout << mn << ' ' << mx << '\n';
                continue;
            }
            else		//如果不能同时被 6 整除,只需带点贪心的思想暴力求解 min 即可
            {
                int t = n, cnt = 0;
                
                while (t % 6 && t >= 0)
                {
                    t -= 4;
                    ++cnt;
                }
                mn = cnt + t / 6;
                cout << mn << ' ' << mx << '\n';
                continue;
            }
        }
		
		//下面情况思想与上一致
        if (n % 6 == 0)
        {
            mn = n / 6;
            
            int t = n, cnt = 0;
            while (t % 4 && t >= 0)
            {
                t -= 6;
                ++cnt;
            }
            mx = cnt + t / 4;
            cout << mn << ' ' << mx << '\n';
            continue;
        }

		//如果既不能被 4 整除又不能被 6 整除,那么需要贪心求解 min  max
		//下面是求 min
        int t = n;
        int cnt = 0;
        bool ok1 = false, ok2 = false;
        while (t % 6 && t >= 0)		//贪心
        {
            t -= 10;		//46 捆绑一组,和为 10,每次循环删去一组
            cnt += 2;		//每删去一组 10,形成的个数要加 2
            if (t % 6 == 0) ok1 = true;		//成功找到最小值
        }
        if (ok1) mn = cnt + t / 6;
        
        //下面是求 max
        int tt = n;
        int num = 0;
        while (tt % 4 && tt >= 0)
        {
            tt -= 10;
            num += 2;
            if (tt % 4 == 0) ok2 = true;
        }
        if (ok2) mx = num + tt / 4;
        
        if (!ok1 && !ok2) { puts("-1"); continue; }		// min  max 均未找到,即无法用 4  6 组合,不过显然这种情况是不存在的,因为只要是大于等于4的偶数,就可以被 4  6 组合而成!
        
        if (!ok1 && ok2)
        {
            mn = mx;
            cout << mn << ' ' << mx << '\n';
            continue;
        }

        if (ok1 && !ok2)
        {
            mx = mn;
            cout << mn << ' ' << mx << '\n';
            continue;
        }

        cout << mn << ' ' << mx << '\n';
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值