洛谷每日一题——P1028 [NOIP2001 普及组] 数的计算、P8468 [Aya Round 1 C] 文文的构造游戏(构造题)

P1028 [NOIP2001 普及组] 数的计算

题目描述

[NOIP2001 普及组] 数的计算 - 洛谷

运行代码

#include <iostream>
using namespace std;
int main(void) {
    int n, p[1001];
    for (int i = 0; i <= 1000; i++)
        p[i] = 1;
    cin >> n;
    for (int i = 2; i <= 1000; i++)
        for (int j = 1; j <= i / 2; j++)
            p[i] += p[j];
    cout << p[n];
    return 0;
}

代码思路

  • 首先定义了一个整数变量 n 和一个大小为 1001 的整数数组 p
  • 然后通过一个循环将数组 p 的所有元素初始化为 1。这个初始化操作的目的可能是为后续的计算设定一个初始状态,具体含义要结合后续代码逻辑进一步明确。
  • 从标准输入读取一个整数,并将其存储到变量 n 中。这个 n 的值将在后续的计算中起到关键作用,很可能决定了数组 p 中某个特定元素的最终计算结果所对应的索引位置。
  • 这里有两层嵌套的循环:
    • 外层循环:从 i = 2 开始,一直到 i = 1000,每次递增 1。对于每一个 i 的值,都要进行内层循环的操作,目的是逐步更新数组 p 中对应索引为 i 的元素的值。
    • 内层循环:对于当前的外层循环变量 i,内层循环从 j = 1 开始,到 j <= i / 2 结束,每次递增 1。在每次内层循环中,将数组 p 中索引为 i 的元素的值累加上数组 p 中索引为 j 的元素的值。也就是说,对于每个 i,它对应的 p[i] 的值会不断累加 p[j](其中 j 满足内层循环条件)的值。这样的计算逻辑可能是基于某种特定的数学关系或者算法需求,通过不断累加前面部分元素的值来得到当前元素的最终结果
  • 最后,将数组 p 中索引为 n 的元素的值输出到标准输出。这里的 n 就是前面从标准输入读取的值,所以程序最终输出的是经过前面一系列计算后,数组 p 中特定索引位置(由用户输入决定)的元素的值

P8468 [Aya Round 1 C] 文文的构造游戏

题目描述

[Aya Round 1 C] 文文的构造游戏 - 洛谷

运行代码

#include <iostream>
#include <vector>
using namespace std;

// 计算向量元素的异或和
long long xorSum(const vector<long long>& arr) {
    long long res = 0;
    for (long long num : arr) {
        res ^= num;
    }
    return res;
}

// 计算向量元素的和
long long sumArray(const vector<long long>& arr) {
    long long res = 0;
    for (long long num : arr) {
        res += num;
    }
    return res;
}

int main() {
    int T;
    cin >> T;

    while (T--) {
        long long s, m;
        cin >> s >> m;

        // 如果s为奇数且m为1,无解
        if (s % 2 == 1 && m == 1) {
            cout << "-1" << endl;
            continue;
        }

        // 如果s为0,构造长度为1,元素为0的向量
        if (s == 0) {
            cout << "1 0" << endl;
            continue;
        }

        int n = 2;
        vector<long long> arr(2);

        // 尝试用两个数构造满足条件的向量
        if (m >= 2) {
            arr[0] = s / 2;
            arr[1] = s / 2;
            if (xorSum(arr) == 0 && sumArray(arr) == s) {
                cout << "2 " << arr[0] << " " << arr[1] << endl;
                continue;
            }
        }

        // 如果前面的情况都不满足,尝试用多个数构造
        // 先将s表示成二进制形式
        vector<long long> binary_s;
        long long temp_s = s;
        while (temp_s > 0) {
            binary_s.push_back(temp_s % 2);
            temp_s /= 2;
        }

        // 从二进制的最低位开始模拟构造向量
        n = binary_s.size();
        vector<long long> c_arr(n);
        for (size_t i = 0; i < n; i++) {
            if (binary_s[i] == 1) {
                c_arr[i] = 1LL << i;
            }
            else {
                c_arr[i] = 0;
            }
        }

        // 检查构造的向量是否满足条件
        if (xorSum(c_arr) == 0 && sumArray(c_arr) == s) {
            cout << n << " ";
            for (long long num : c_arr) {
                cout << num << " ";
            }
            cout << endl;
        }
        else {
            cout << "-1" << endl;
        }
    }

    return 0;
}

代码思路

给定两个整数 s 和 m,尝试构造一个整数向量(vector<long long>),使得该向量元素的异或和为 0,并且向量元素的和等于 s。根据不同的条件,代码会尝试用不同的方式来构造满足要求的向量,如果无法构造出满足条件的向量,则输出 -1

  • xorSum 函数
long long xorSum(const vector<long long>& arr) {
    long long res = 0;
    for (long long num : arr) {
        res ^= num;
    }
    return res;
}
  • 这个函数接受一个整数向量 arr 作为参数。

  • 通过遍历向量中的每个元素 num,使用异或操作(^)将每个元素依次与结果变量 res 进行异或运算。

  • 最终返回向量元素的异或和。异或运算的特点是:相同的数异或为 0,不同的数异或为非零值。所以当向量中某些元素经过特定组合的异或运算后结果为 0,就满足了部分题目要求。

  • sumArray 函数

long long sumArray(const vector<long long>& arr) {
    long long res = 0;
    for (long long num : arr) {
        res += num;
    }
    return res;
}
  • 同样接受一个整数向量 arr 作为参数。
  • 遍历向量中的每个元素 num,并将其累加到结果变量 res 上。
  • 最后返回向量元素的总和,用于判断构造的向量元素之和是否等于给定的 s

1. 输入处理

  • 首先读取一个整数 T,它表示接下来要处理的测试用例的数量。
  • 然后在一个循环中(循环 T 次),每次读取两个整数 s 和 m,这两个整数就是每次测试用例中需要根据其构造满足条件向量的关键参数。

2. 特殊情况处理

// 如果s为奇数且m为1,无解
if (s % 2 == 1 && m == 1) {
    cout << "-1" << endl;
    continue;
}

// 如果s为0,构造长度为1,元素为0的向量
if (s == 0) {
    cout << "1 0" << endl;
    continue;
}
  • 当 s 为奇数且 m 为 1 时,根据题目要求或者某种内在逻辑(可能因为奇数无法通过一个数满足异或和为 0 且和为该奇数本身的条件),直接判定为无解,输出 -1 并跳过本次循环的后续处理。
  • 当 s 为 0 时,构造一个长度为 1,元素为 0 的向量即可满足条件,所以输出 1 0 并跳过后续处理。

3. 尝试用两个数构造向量

int n = 2;
vector<long long> arr(2);

// 尝试用两个数构造满足条件的向量
if (m >= 2) {
    arr[0] = s / 2;
    arr[1] = s / 2;
    if (xorSum(arr) == 0 && sumArray(arr) == s) {
        cout << "2 " << arr[0] << " " << arr[1] << endl;
        continue;
    }
}
  • 当 m >= 2 时,尝试用两个数来构造满足条件的向量。
  • 将 s 平均分成两份,分别赋给向量 arr 的两个元素 arr[0] 和 arr[1]
  • 然后通过调用 xorSum 和 sumArray 函数来检查这个构造的向量是否满足异或和为 0 且和为 s 的条件。如果满足,则输出向量的长度 2 以及这两个元素的值,然后跳过本次循环的后续处理。

4. 尝试用多个数构造向量

// 如果前面的情况都不满足,尝试用多个数构造
// 先将s表示成二进制形式
vector<long long> binary_s;
long long temp_s = s;
while (temp_s > 0) {
    binary_s.push_back(temp_s % 2);
    temp_s /= 2;
}

// 从二进制的最低位开始模拟构造向量
n = binary_s.size();
vector<long long> c_arr(n);
for (size_t i = 0; i < n; i++) {
    if (binary_s[i] == 1) {
        c_arr[i] = 1LL << i;
    }
    else {
        c_arr[i] = 0;
    }
}

// 检查构造的向量是否满足条件
if (xorSum(c_arr) == 0 && sumArray(c_arr) == s) {
    cout << n << " ";
    for (long long num : c_arr) {
        cout << num << " ";
    }
    cout << endl;
}
else {
    cout << "-1" << endl;
}
  • 如果前面用两个数构造向量的尝试失败,就尝试用多个数来构造。
  • 首先将整数 s 转换成二进制形式,存储在向量 binary_s 中。
  • 然后从二进制的最低位开始,根据二进制位的值来构造向量 c_arr。如果二进制位为 1,则将对应位置的向量元素设置为 2 的相应幂次方(通过 1LL << i 实现);如果二进制位为 0,则设置为 0
  • 最后通过调用 xorSum 和 sumArray 函数来检查这个构造的向量是否满足异或和为 0 且和为 s 的条件。如果满足,则输出向量的长度以及各个元素的值;如果不满足,则输出 -1,表示无法构造出满足条件的向量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

筱姌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值