codeforce. C. Perfect Team

题意: 有a,b,c三种数,有多少种三个数的组合,使得每组数,至少一个a一个b。

思路: 二分是很显然的,但是还可以推公式。比赛的时候写的是二分。赛后看大牛的代码,貌似就3种情况:x,y,(x+y+z)/3。取最小值就可以了。理由的话,就是按种类数足的话,就按人数取,种类数不足的话,就按照种类数取。

但是这样感觉还是不自然(没有严谨的数学推理)。
假设三类数数目分别为x,y,z。令a = min(x, y) ,b = x + y + z - 3 * a。那么,a代表能组成最多多少组,b代表组成a组后剩下的人数。如果b >= 0,很明显可以组成a组,那就输出a。否则,那组成的组数就小于a组,那么此时所有数都分组,就是(x+y+z)/3,此时组数小于a组,那么种类数的条件一定能满足。

同理可证,x,y,z,d,每组4个人,至少一个x和y和z,则结果也是一样,min(x,y,z,(x+y+z+d))。更多的数也是这样推。

再拓展思考一下,要是是n种数,1~n-1种数有效,每组数有n个,至少m个不同有效种类数。问最多组成多少组?就贪心的一下选数目最多的m个有效种类数就可以了。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

typedef long long ll;
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
        ll x = min(a,b);
        ll y = a + b + c - 3 * x;
        if(y >= 0)
        {
            printf("%lld\n",x);
        }
        else
        {
            printf("%lld\n",(3 * x + y) / 3);
        }
    }
    return 0;
}

二分:


#include <cstdio>
#include <algorithm>
#include <algorithm>

using namespace std;

typedef long long ll;
const ll mod = 1e9 + 7;

int main()
{
    int n;scanf("%d",&n);
    while(n--)
    {
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        int r = min(a,b),l = 0;
        int sum = a + b + c;
        int ans = 0;
        while(l < r)
        {
            int m = (l + r + 1) >> 1;
            if(m * 3 == sum)
            {
                ans = m;
                break;
            }
            else if(m * 3 > sum)
            {
                r = m - 1;
            }
            else
            {
                ans = m;
                l = m;
            }
        }

        printf("%d\n",ans);
    }
}

发布了107 篇原创文章 · 获赞 3 · 访问量 7103

猜你喜欢

转载自blog.csdn.net/qq_43504141/article/details/104492959