笔试刷题-头条

题目描述:

/**
有三只球队,每只球队编号分别为球队1,球队2,球队3,这三只球队一共需要进行 n 场比赛。
现在已经踢完了k场比赛,每场比赛不能打平,踢赢一场比赛得一分,输了不得分不减分。
已知球队1和球队2的比分相差d1分,
球队2和球队3的比分相差d2分,
每场比赛可以任意选择两只队伍进行。
求如果打完最后的 (n-k) 场比赛,有没有可能三只球队的分数打平。

输入描述:
第一行包含一个数字 t (1 <= t <= 10)
接下来的t行每行包括四个数字 n, k, d1, d2(1 <= n <= 10^12; 0 <= k <= n, 0 <= d1, d2 <= k)

输出描述:
每行的比分数据,最终三只球队若能够打平,则输出“yes”,否则输出“no”

输入例子1:
2
3 3 0 0
3 3 3 3

输出例子1:
yes
no

例子说明1:
case1: 球队1和球队2 差0分,球队2 和球队3也差0分,所以可能的赛得分是三只球队各得1分
case2: 球队1和球队2差3分,球队2和球队3差3分,所以可能的得分是 球队1得0分,球队2得3分, 球队3 得0分,比赛已经全部结束因此最终不能打平。
*/

思路如下:

暴力穷举4中可能情况 设第一队为x;  第二队为 x-d1 或 x+d1; 第三队类似推导 解出 (score1, score2, score3)的合法元组
然后看剩余的n-k能否让 (score1, score2, score3)->(n/3, n/3, n/3)

代码如下:

#include<stdio.h>
#include<iostream>

using namespace std;

typedef long long LL;

void GetABC(int i, LL a, LL *pb, LL *pc, LL d1, LL d2)
{
    switch (i)
    {
    case 0:
        *pb = a + d1;
        *pc = *pb + d2;
        break;
    case 1:
        *pb = a + d1;
        *pc = *pb - d2;
        break;
    case 2:
        *pb = a - d1;
        *pc = *pb + d2;
        break;
    case 3:
        *pb = a - d1;
        *pc = *pb - d2;
        break;
    }
}

int main()
{
    int T;
    for (cin >> T; T--; )
    {
        LL n, k, d1, d2;
        scanf("%lld%lld%lld%lld", &n, &k, &d1, &d2);
        //x的四种可能解的3倍,就是第一场可能出现的解
        //第一场的分数的3倍
        LL x[] = {k - 2 * d1 - d2,k - 2 * d1 + d2,k + 2 * d1 - d2,k + 2 * d1 + d2};
        bool flag = false;
        for (int i = 0; i < 4; i++)
        {
            int sum = 0;
            //判断第一场的分数是否为3的倍数
            for (LL t = x[i]; t; sum += t % 10, t /= 10) {}
            //第一场分数要合法才美剧判断
            if (sum % 3 == 0 && 0 <= x[i] / 3 && x[i] / 3 <= k)
            {
                LL a = x[i] / 3, b, c;
                //计算根据第一场x的不同情况,计算4中情况对应的第一场第二场的分数
                GetABC(i, a, &b, &c, d1, d2);
                if (0 <= b && b <= k && 0 <= c && c <= k)
                {
                    LL maxNum = max(a, max(b, c));
                    LL diff = 3 * maxNum - a - b - c;
                    //剩下的场次,若先让最小的两个都抹平达到最大的一个分数,剩下的分数要是能平分给3队即可
                    if (n - k - diff >= 0 && (n - k - diff) % 3 == 0)
                    {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if(flag)
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值