A.比大小

解题思路

已知

  1. 芭芭拉比迪奥娜大;
  2. 可莉比芭芭拉小;
  3. 可莉比迪奥娜小。

容易得到:芭芭拉大于迪奥娜大于可莉

直接输出即可

AC_Code

#include <stdio.h>  

int main() {

    puts("芭芭拉");
    puts("可莉");

    return 0;
}

B.两艘船

解题思路

为船中货物的质量差。我们的目标是使 等于 。请注意,只要运一次,我们就可以把 范围内的任何数字相加。因此,问题的答案将是

AC_Code

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

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

    while (t--) {
        float a, b, c;
        int ans;
        scanf("%f %f %f", &a, &b, &c);
        int tem = abs(a - b);
        int res = tem / (2 * c);
        if(res * (2 * c) == tem) 
            printf("%d\n", res);
        else
            printf("%d\n", res + 1);
    }

    return 0;
}

C.活动

解题思路

反向思考,如果有 个人,在能确定毒药位置的情况下所允许的最多的水的杯数是多少?

我们把 个人排成一列,看作一个 位的二进制整数,可以发现有 种不同的方案去喝水。

时,可以确定 杯水中毒药的位置。

转化一下,就有

AC_Code

#include <stdio.h>
#include <math.h>

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

    if(n == 1) 
    {
    	printf("%d\n", 0);
    }
    else
    {
	    int res = log2(n + 1);
        if (pow(2, res) < n) res ++;

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

    return 0;
}

D.理想点

解题思路

首先,让我们删除所有不覆盖点 的线段(因为它们会增加函数 以外的点上的值)。如果没有剩余的线段,那么答案就是 "否"。否则,所有线段都覆盖了点 。剩下的工作就是检查点 是否是唯一一个被所有线段覆盖的点。需要注意的是,删除任何剩余的线段都是没有意义的,因为如果有几个点的最大值是 ,那么删除线段只会增加它们的数量。

要检查最大值为 的点的数量,可以从 遍历 ,然后计算 ,因为问题中的线段数量很少。更快捷的方法是检查所有线段交集的大小。交点的左边界是 ,右边界是 ;如果是 ,那么点 是理想点,否则不是。

AC_Code

#include <stdio.h>
#include <math.h>

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int n, k;
        scanf("%d %d", &n, &k);
        int L = 0, R = 55;
        while (n--) {
            int l, r;
            scanf("%d %d", &l, &r);
            if (l <= k && k <= r)
            {
                L = (L > l)? L : l;
                R = (R < r)? R : r;               
            }
        }
        if(L == R) puts("YES");
        else puts("NO");
    }
}

E.交易

解题思路

时,小宇可以选择通过多次交易来赚取银币, 所以只需完成游戏中的一个任务即可。

时,小宇只能通过完成游戏中的任务的方式赚钱,所以所需完成的最小任务数为

AC_Code

#include <stdio.h>
#include <math.h>

int main() {
    int t; 
    scanf("%d", &t);
    while(t -- ) 
    {
        int n, a, b; 
      	scanf("%d %d %d", &n, &a, &b);

      	if(a > b) 
      	{
            printf("1\n");
        }
        else 
        {
            if((int)(n / a) * a == n) printf("%d\n", n / a);
            else printf("%d\n", n / a + 1);
        }
    }
      
    return 0;
}

F.烦恼

解题思路

给定:

已知 ,求

拆一下上面的式子,得:

根据第一个式子,得到

代入第二个式子:

因为 已知,,算出判别式:

代入算出 的公式:

直接计算即可。

AC_Code

#include <stdio.h>
#include <math.h>

int main() {

    int t; scanf("%d", &t);
    while(t -- )
    {
        long long n, e, d; 
        scanf("%lld %lld %lld", &n, &e, &d);
        long long m = n - e * d + 2;
        long long delta = m * m - 4 * n;
        long long q = sqrt(delta);
        if(delta < 0 || q * q != delta || (m + q) % 2) {
            puts("NO");
            continue;
        }

        q = (m + q) / 2;
        long long p = n / q;
        if(p * q != n || p < 0 || q < 0) {
            puts("NO");
            continue;
        }

        printf("%lld %lld\n", p, q);
    }

    return 0;
}

G.行走大师

解题思路

提示 1: 的值总是不递减的,而 的值总是不递增的。

当且仅当 时,才有可能从 移动到 ,因为 的值总是不递减的,而 的值总是不递增的。

如果可能,答案就是 。一种可能的方法是

另一种理解方式是如果可以从 移动到 ,那么 总是一条有效的路径。因此首先假设 ,那么答案只取决于

AC_Code

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main() 
{
    int T; 
    scanf("%d", &T);
    while(T -- ) 
    {
        int a, b, c, d; 
        scanf("%d %d %d %d", &a, &b, &c, &d);

        if(b <= d && c <= a + d - b) {
            printf("%d\n", (d - b) + (a + d - b - c));
        } else {
            puts("-1");
        }
    }
 
    return 0;
}