P1028 [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] 文文的构造游戏
题目描述
运行代码
#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
,表示无法构造出满足条件的向量。