答案解析5

A、装水

  1. 操作 1:手动加水(需最小化);
  2. 操作 2:移动水(无次数限制,可跨空段移动);
  3. 自动填充:若空单元格i(2≤i≤n-1)左右都有水,会自动填满;
  4. 关键推论:只要存在≥3 个连续的空单元格,仅需 2 次操作 1 就能填满所有空单元格(其余空单元格可通过 "自动填充 + 操作 2 移动水" 覆盖);若不存在≥3 个连续空单元格,则每个空单元格都需手动加 1 次水。
cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
 
int main() {
    int n;
    scanf("%d", &n);
    while (n--) {
        int m;
        scanf("%d", &m);
        char* str = (char*)malloc((m+5) * sizeof(char));
        scanf("%s", str);
 
        int w = 0, count = 0;
        for (int i = 0; i < m-2; i++){
            if (str[i] == '.' && str[i + 1] == '.' && str[i + 2] == '.') {
                w = 1;
                break;
            }   
        }
        for (int i = 0; i < m; i++) if (str[i] == '.')count++;
 
        if (w == 1){
            printf("2\n"); 
            continue;
        }
        else printf("%d\n", count);
    }
     
    return 0;
}

B、签到签到

这个问题的核心是双指针法(夹逼法),利用 "x²+y² 随 x 增大、y 减小的单调性",在 O (√D) 时间复杂度内找到使 | x²+y²-D | 最小的非负整数对 (x,y),避免暴力枚举所有可能的 x、y(暴力枚举会超时,因为 D 最大到 1e12,√D 约 1e6,双指针法效率极高)。

核心原理

对于非负整数 x、y:

  1. x²+y² 的取值范围:最小为 0(x=y=0),最大无界,但我们只需要找到最接近 D 的取值;
  2. 单调性:固定 x 时,y 越大,x²+y² 越大;固定 y 时,x 越大,x²+y² 越大;
  3. 双指针策略:
    • 初始时,x 从 0 开始(最小),y 从√D 开始(最大的可能使 y²≤D 的数);
    • 通过调整 x 和 y 的大小,逐步逼近 "x²+y²=D" 的状态,过程中记录最小差值。
cpp 复制代码
#include<stdio.h>
#include<math.h>
int main() {
    long long D;
    scanf("%lld", &D);
    long long x = 0;
    long long y = (long long)sqrt(D);
    long long min_diff = D;
    while (x <= y) {
        long long cur = x * x + y * y;
        long long diff = cur - D;
        if (diff < 0) {
            diff = -diff;
        }
        if (diff < min_diff) {
            min_diff = diff;
        }
        if (cur > D) {
            y--;
        }
        else {
            x++;
        }
    }
    printf("%lld\n", min_diff);
    return 0;
}

C、热爱物理的zwz

这个问题的核心是利用 "光的全反射对称原理" 推导激光的入射向量,再通过 "最大公约数(GCD)约分" 保证输出向量的最简形式(gcd (i,j,k)=1)。

物理反射原理(核心推导)
  1. 坐标系定义:

    • zwz 位置为原点 (0,0,0),水面是 z=h 的平面(zwz 在水下,距离水面高度为 h,因此水面的 z 坐标是 h);
    • 目标位置为 (x,y,z),激光需先射到水面,经一次全反射后到达目标
  2. 反射的 "镜像法"(关键!):光的反射可等效为 "激光沿直线射向目标的镜像点",镜像点的计算规则:

    • 水面是 z=h,目标点 (x,y,z) 关于水面的镜像点 z 坐标为:h + (h - z) = 2h - z(x、y 坐标不变);
    • 因此,激光的入射向量就是从原点 (0,0,0) 指向镜像点 (x, y, 2h - z) 的向量,即初始向量为(x, y, 2h - z)

    👉 样例验证:样例输入 h=5,目标 (3,3,2) → 镜像点 z 坐标 = 2*5 -2=8 → 初始向量为 (3,3,8)(与样例输出一致,且该向量 gcd=1,无需约分)。

cpp 复制代码
#include<stdio.h>
int main()
{
    int n, a,b,c;
    scanf("%d", &n);
    scanf("%d %d %d", &a,&b,&c);
    int u, uu;
    if (n != 0)
        u = n - c + n;
    else
        u = c;
    if (a < b) {
        uu = a;
    }
    else {
        uu = b;
    }
    if (uu > u) {
        uu = u;
    }
    for (int i = uu; i >= 2; i--) {
        if (a % i == 0 && b % i == 0 && u % i == 0) {
            a = a / i;
            b = b / i;
            u = u / i;
            i++;
        }
    }
    printf("%d %d %d", a, b, u);
    return 0;
}

D、学的太少了,水题凑一下好了

cpp 复制代码
#include<stdio.h>
 
int num(int a, int b) {
    if (b == 0) return a;
    else return num(b, a % b);
}
 
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    int t = num(n, m);
    printf("%d", t);
}

E、奇怪的等式

这个问题的核心是通过数学公式构造满足条件的整数解 (x,y,z),而非暴力枚举(暴力枚举会因 n 范围大而超时),同时对特殊值(n=0、n=1)直接判定无解。

关键数学推导(构造解的核心)

题目要求找到互不相同的整数 x,y,z,满足:x1​+y1​+z1​=n2​

步骤 1:简化问题,先固定两个变量

我们尝试构造一组通用解,选择x = n(第一个变量),代入等式:n1​+y1​+z1​=n2​化简得:y1​+z1​=n1​

步骤 2:构造 y 和 z 的解

对 y1​+z1​=n1​,我们需要找两个互不相同的整数 y、z,且与 x=n 也互不相同。经典的分数拆分技巧:令 y=n+1(第二个变量),代入得:z1​=n1​−n+11​=n(n+1)(n+1)−n​=n(n+1)1​因此 z=n(n+1)(第三个变量)。

步骤 3:验证构造的解是否满足所有条件

构造的解为:

  • x=n
  • y=n+1
  • z=n(n+1)

验证等式:n1​+n+11​+n(n+1)1​=n(n+1)(n+1)+n+1​=n(n+1)2n+2​=n(n+1)2(n+1)​=n2​完全满足原式!

同时验证 "互不相同":

  • n ≥ 2 时,n <n+1 < n (n+1)(如 n=3 时,3 < 4?不,样例中 n=3 时 y=7?哦,样例是特殊构造,核心逻辑是 "存在通用构造解",样例的解是另一组有效解,代码的构造解是更通用的)。

特殊值判断(n=0、n=1 无解)

  1. n=0:原式右边 02 无意义,直接判定无解;
  2. n=1:代入构造解得 x=1、y=2、z=2,z 与 y 重复(不满足 "互不相同"),且无其他有效解,判定无解;
  3. n≥2:构造的 x=n、y=n+1、z=n (n+1) 互不相同,且满足等式,因此有解。
cpp 复制代码
#include <stdio.h>
int main ()
{
    int n,x,y,z;
    scanf("%d",&n);
     
    x=n;
    y=n+1;
    z=(n+1)*n;
     
    if(n==0||n==1)
    {
        printf("小王大王");
    }else
    {
        printf("%d %d %d",x,y,z);
    }
    return 0 ;
}

F、路径

这个问题的核心是动态规划(DP)求解网格最短路径数,结合 "只能向右 / 向下走(最短路径的唯一走法)" 的规则,通过状态转移方程递推所有路径数,最终对结果取模。

问题本质(最短路径的约束)

网格中从起点 (0,0) 到终点 (n-1,m-1) 的最短路径,只能由 "向右(→)" 和 "向下(↓)" 两种移动组成(任何向左 / 向上的移动都会增加路径长度)。

  • 最短路径的总步数固定:需要走 (n-1) 次向下 + (m-1) 次向右 = n+m-2 步;
  • 路径数等价于:在 n+m-2 步中选择 n-1 步向下(或 m-1 步向右)的组合数,即 C(n+m−2,n−1)(组合数公式)。
cpp 复制代码
#include<stdio.h>
#include<math.h>
#define N 2000
int a[N][N];
int main() {
    int n, m, i, j;
    scanf("%d%d", &n, &m);
    for ( i = 0; i <N; i++)
    {
        a[i][0] = 1;
        a[0][i] = 1;
    }
    for ( i = 0; i <n; i++)
    {
        for ( j = 0;  j <= m;  j++)
        {
            a[i + 1][j + 1] = (a[i][j + 1] + a[i + 1][j]) % 1000000007;
        }
    }
    printf("%d", a[n-1][m-1]);
    return 0;
}
相关推荐
CircleMouse3 小时前
如何设置wps单元格下拉选项设置
excel·wps
zhangjin12228 小时前
kettle插件-excel插件,kettle读取excel动态表头,kettle根据列名读取excel
excel·kettle·kettle excel插件·kettle 动态excel
远洪1 天前
excel 找出两列不同的数据
excel
pcplayer1 天前
非常好用的 Excel 读写控件
excel·delphi·office
Navicat中国1 天前
使用 Navicat 导入向导导入 Excel 数据时,系统提示导入成功,表中也能看到数据,但行数统计显示为 0,这是什么原因?
数据库·excel·导入
穿着内裤的外星人1 天前
触控精灵远程读写Excel步骤配置
excel
是孑然呀1 天前
【小记】excel vlookup一对多(第二篇)
excel
开开心心就好1 天前
专为视障人士设计的免费辅助工具
windows·计算机视觉·计算机外设·excel·散列表·推荐算法·csdn开发云
transformer_WSZ1 天前
excel两列数据绘制折线图
excel·折线图
蒋胜山2 天前
Excel 练习题(5)
经验分享·excel