牛客周赛 Round 60(上)

困难数学题

题目描述

登录—专业IT笔试面试备考平台_牛客网

运行代码

#include <iostream>
using namespace std;
int main() {
    int x;
    cin >> x;
    int y = x ^ x ^ x ^ x;
    cout << y <<endl;
    return 0;
}

代码思路

一、整体思路

  1. 首先从用户输入中读取一个整数 x,这个 x 的取值范围是 0 ≤ x ≤ 500
  2. 然后根据题目要求的运算规则,计算 y = x ^ x ^ x ^ x
  3. 最后将计算得到的结果 y 输出。

二、异或运算(^)原理

异或运算的规则是:对于两个二进制位,如果相同则结果为 0,不同则结果为 1。

例如:

  • 0 ^ 0 = 0
  • 1 ^ 1 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1

三、代码中异或运算的具体分析

在计算 y = x ^ x ^ x ^ x 时:

  1. 当 x 为一个确定的值时,比如 x = 5(二进制表示为 00000101)。

    • x ^ x 的结果为 0,因为相同的位进行异或运算结果为 0。
    • 所以 x ^ x ^ x ^ x 就相当于 0 ^ x ^ x
    • 又因为 0 ^ a = a(任何数与 0 进行异或运算结果为其本身)。
    • 所以 0 ^ x ^ x 的结果还是 0 ^ x,即 x ^ x ^ x ^ x = x ^ x = 0
  2. 对于任意的 x,都有相同的结论。因为无论 x 的二进制表示是什么,x 与自身进行异或运算结果总是 0,多个 x 进行异或运算最终结果也为 0。

综上所述,这段代码通过读取输入的整数 x,利用异或运算的特性,计算并输出了符合题目要求的结果 y

折返跑

题目描述

登录—专业IT笔试面试备考平台_牛客网

运行代码

#include <iostream>

typedef long long ll;
const int M = 1e6 + 5;
const ll mod = 1e9 + 7;

ll qpow(ll x, ll ci) {
    ll ans = 1;
    while (ci > 0) {
        if (ci & 1) ans = ans * x % mod;
        x = x * x % mod;
        ci >>= 1;
    }
    return ans;
}

int main() {
    ll fac[M];
    fac[0] = 1;
    for (ll i = 1; i < M; i++) fac[i] = fac[i - 1] * i % mod;
    int t;
    std::cin >> t;
    while (t--) {
        int n, m;
        std::cin >> n >> m;
        n -= 2;
        m--;
        if (n < m) std::cout << "0\n";
        else std::cout << fac[n] * qpow(fac[m], mod - 2) % mod * qpow(fac[n - m], mod - 2) % mod << '\n';
    }
    return 0;
}

代码思路

一、整体思路

  1. 首先定义了常量 M 和 mod,分别表示一个较大的数和取模的值。
  2. 定义了快速幂函数 qpow,用于高效地计算一个数的幂次方对 mod 取模的结果。
  3. 在 main 函数中:
    • 初始化一个长度为 M 的数组 fac,用于存储阶乘的值,其中 fac[0] 初始化为 1,通过循环计算出 fac[1] 到 fac[M - 1] 的值,每个值都是前一个值乘以当前索引对 mod 取模的结果。
    • 读取测试数据组数 t
    • 对于每组测试数据:读取点位数量 n 和折返跑趟数 m。对 n 和 m 进行处理,将 n 减去 2,m 减去 1,以便后续计算。如果处理后的 n 小于 m,说明没有合法的推杆方法,输出 0。否则,根据组合数的计算公式,输出 fac[n] * qpow(fac[m], mod - 2) % mod * qpow(fac[n - m], mod - 2) % mod 的结果,即从 n 个空位中选择 m 个位置的组合数对 mod 取模的结果。

二、原理分析

  1. 组合数计算:组合数的计算公式为 。在代码中,通过预先计算出阶乘数组 fac,然后利用公式计算组合数。为了避免除法运算可能导致的精度问题,使用了逆元的方法。对于整数 a 和 mod,如果 a 和 mod 互质,那么 a 在模 mod 下的逆元 inv(a) 满足 a * inv(a) ≡ 1 (mod mod)。在代码中,通过快速幂函数计算 fac[m] 和 fac[n - m] 在模 mod 下的逆元,然后与 fac[n] 相乘得到组合数。

  2. 快速幂与取模:快速幂函数 qpow 使用了位运算的技巧来高效地计算幂次方。通过不断将指数 ci 右移一位,同时将底数 x 平方,如果当前指数的最低位为 1,则将结果累乘上当前的底数。这样可以在对数时间内计算出幂次方的结果,同时通过不断对中间结果取模,避免了数值过大导致的溢出问题。

  3. 问题的转化:对于给定的 n 个点位和 m 趟折返跑,每次折返都需要推杆,相当于在 n - 2 个空位中选择 m - 1 个位置来放置右杆的移动位置。这是因为第一次折返前,右杆在位置 2,最后一次折返后,右杆在位置 n - 1,所以有 n - 2 个空位可供选择。而选择 m - 1 个位置是因为有 m - 1 次右杆的移动。根据组合数的定义,这就是从 n - 2 个元素中选择 m - 1 个元素的组合数,即问题的答案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值