第二次周作业题解

A题

思路:题目意思是选一个重量值使得第一个人赢,那么如果有一个人力量大于等于第一个人且耐力大于等于第一个人则第一个人必输输出 -1
如果没有这样的人则第一个人必赢,题目要求输出任意允许第一个人赢的重量值,那么我们只需要输出第一个人的力量值即可 

#include <stdio.h>

int max(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    int t;
    scanf("%d", &t);

    while (t--)             //t 组测试样例
    {
        int n;
        scanf("%d", &n);    //n 个人
        int firstPower, firstEndurance;
        scanf("%d %d", &firstPower, &firstEndurance);    //第一个人的力量和耐力
        int maxEndurance = 0;          //记录力量大于第一个人的人中耐力最大的人的耐力
        for (int i = 2; i <= n; i++)
        {
            int power, endurance;
            scanf("%d %d", &power, &endurance);
            if (power >= firstPower)                 //如果力量大于第一个人的力量
            {
                maxEndurance = max(maxEndurance, endurance);
            }
        }
        if (maxEndurance >= firstEndurance)          //如果有人力量大于等于第一个人且耐力大于第一个人则第一个人必输
        {
            printf("-1\n");
        }
        else
        {
            printf("%d\n", firstPower);
        }
    }
    return 0;
}

 B题

思路:首先可以看出每一斜列的数的数量与列数相等,即第i斜列有i个数。那么我们可以定义一个变量t从第一列开始加上每一列的数量i,直到t>n为止,这时我们可以看出看出n与t的差即为n在第i列中的某一个,但由题目得每一列有时从左下到右上,有时从右上到左下。

我们可以画图看出i为奇数时第i列是左下到右上,i为偶数时第i列是从右上到左下,故可判断出n为第i列的中哪一个

#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);
    int t = 0, i = 1;    //t从第一列开始逐加
    while (t < n) {    
        t += i;
        i++;
    }
    i--;
    int d = t - n;
    if (i % 2 == 0) {
        printf("%d/%d\n", i - d, 1 + d);    //i为偶数时即右上往左下数第d个
    } else {
        printf("%d/%d\n", 1 + d, i - d);    //i为奇数时即左下往右上数第d个
    }
    return 0;
}

C题

思路:

因为数据范围有点大,运算之后可能超过int的数据范围,所以都用longlong。

由题可知取的h越大需要的水量越大,由此单调性可用二分法解决该题。

最先从1到无限大中取一个中间值判断该值是否满足补充水的要求,如果能满足要求那么继续往右区间寻找更大的h,如果不满足要求那么往左区间寻找满足条件的h

#include <stdio.h>

long long a[200010];
long long n, x;

bool check(long long h)
{
    long long res = 0;
    for (int i = 1; i <= n; i++)   // 遍历每个数
    {
        if (a[i] < h)           // 如果小于 h,需要补充水
        {
            res += h - a[i];
        }
        if (res > x)        // 如果补充的水超过了 x,说明不满足条件
            return false;
    }
    return true;        // 否则满足条件
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &x);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);

        long long l = 1, r = 0x3f3f3f3f3f3f3f3f;//0x3f3f3f3f3f3f3f3f 对应十进制是 4557430888798830399,是一个很大的数
        while (l < r)
        {
            long long mid = (l + r + 1) / 2;  // 二分查找取中间值
            if (check(mid))        // 检查是否满足条件
                l = mid;            // 满足条件则更新左边界
            else
                r = mid - 1;        // 不满足条件则更新右边界
        }
        printf("%lld\n", l);
    }
}

D题

思路:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值