一、逆序数的计算
逆序数(Inversion)是指在一个序列中,如果两个元素的顺序与它们在原序列中的顺序相反,
即前面的元素大于后面的元素,则这两个元素构成一个逆序数。逆序数反映了序列的无序程
度,逆序数越多,序列的无序程度越高。
#include <iostream>
#include <vector>
using namespace std;
// 归并排序函数,用于排序并计算逆序数
long long mergeSort(vector<int>& nums, int left, int right) {
if (left >= right)
return 0;
int mid = left + (right - left) / 2;
long long inversions = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
// 合并两个有序子数组
int i = left, j = mid + 1;
vector<int> sorted;
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) {
sorted.push_back(nums[i]);
i++;
} else {
sorted.push_back(nums[j]);
j++;
inversions += mid - i + 1; // 计算逆序数
}
}
while (i <= mid) {
sorted.push_back(nums[i]);
i++;
}
while (j <= right) {
sorted.push_back(nums[j]);
j++;
}
// 将排序后的结果复制回原数组
for (int k = left; k <= right; k++) {
nums[k] = sorted[k - left];
}
return inversions;
}
// 计算逆序数的函数
long long countInversions(vector<int>& nums) {
return mergeSort(nums, 0, nums.size() - 1);
}
int main() {
int n;
cout << "Enter the length of the sequence: ";
cin >> n;
vector<int> nums(n);
cout << "Enter the sequence: ";
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
long long inversions = countInversions(nums);
cout << "Number of inversions: " << inversions << endl;
return 0;
}
在上述代码中,使用归并排序的思想来计算逆序数。首先,定义了一个归并排序的函数
mergeSort,该函数接受一个整数向量 nums,以及待排序区间的左右边界 left 和 right。在
mergeSort 函数中,首先递归地将待排序的区间分成两半,然后分别对左右两个子区间进行
归并排序。在合并两个有序子数组的过程中,同时计算逆序数。当左子数组中的一个元素大
于右子数组中的一个元素时,将逆序数增加 mid - i + 1,其中 mid 是左子数组的最后一个
元素的下标,i 是左子数组的当前元素的下标。
接下来,定义了一个计算逆序数的函数 countInversions,该函数接受一个整数向量 nums。
在这个函数中,调用 mergeSort 函数来计算逆序数,并返回结果。
在 main 函数中,首先读取输入的序列的长度 n,然后读取序列的元素。接下来,调用
countInversions 函数计算逆序数,并输出结果
二、QHU 高数&线代&概率论
最近小浪爱上了高数&线代&概率论,今天中午放学时他的老师给了他一个[a,b]的区间,然后
说:首先你要将[a,b]种所有的数全部转化成“十六进制”,别急,还有要把这些数按顺序(比
如说[10,12],按顺序连起来就是 ABC,[20,22]按顺序连起来就是 141516)连起来,将连起来的
数再转化成“十进制”,最后将最终结果对 15 取模。
#include <stdio.h>
// 将一个十进制数转换为十六进制字符串
void decToHex(int dec, char hex[]) {
sprintf(hex, "%X", dec);
}
// 将一个区间内的数按顺序连接并转换为十进制
int concatenateAndConvertToDec(int a, int b) {
char hex[100]; // 用于存储十六进制字符串
char concatenatedHex[100]; // 用于存储连接后的十六进制字符串
int index = 0; // 连接后的十六进制字符串的索引
for (int i = a; i <= b; i++) {
decToHex(i, hex); // 将当前数转换为十六进制
int j = 0;
while (hex[j] != '\0') {
concatenatedHex[index++] = hex[j++]; // 连接十六进制字符串
}
}
concatenatedHex[index] = '\0'; // 添加字符串结束符
int dec = strtol(concatenatedHex, NULL, 16); // 将连接后的十六进制字符串转换为十进
制
return dec;
}
int main() {
int a, b;
printf("请输入区间的起始值 a:");
scanf("%d", &a);
printf("请输入区间的结束值 b:");
scanf("%d", &b);
int result = concatenateAndConvertToDec(a, b);
int mod = result % 15;
printf("最终结果对 15 取模的值为:%d\n", mod);
return 0;
}
三、QHU 军训有射击
QHU 军训又开始了,但是这次不一样,教官增加了射击这一项目,小南想这是我第一次射
击打靶,心里十分开心,但是教官说完话,才知道只是个游戏,唉,但是回答正确的人可以
少站 1 小时的军姿,哇,这简直太爽了,那就请看题吧:
教官面前有一群高度不一的敌人,他手里拿着一把能削减敌人高度的枪,我们称为“QHU 神
枪”,这把“QHU 神枪”射出的子弹会在敌人间跳跃,一发子弹就能对所有敌人的高度减少 2,
如果该子弹导致了任意敌人高度小于等于 0,该子弹还会再次让所有敌人的高度减少 2,直
到没有新的敌人高度小于等于 0 为止。
那么,教官使用“QHU 神枪”要打出几颗子弹才能使所有敌人的高度都小于等于 0 呢?
#include <stdio.h>
#include <stdlib.h>
int calculateBullets(int height[], int numEnemies) {
int bullets = 0;
int i;
while (1) {
int negativeHeight = 0;
// 射击过程
for (i = 0; i < numEnemies; i++) {
if (height[i] > 0) {
height[i] -= 2;
if (height[i] <= 0) {
negativeHeight++;
}
}
}
// 检查是否还有新的敌人高度小于等于 0
if (negativeHeight == 0) {
break;
}
// 如果有新的敌人高度小于等于 0,则再次让所有敌人的高度减少 2
bullets++;
}
return bullets;
}
int main() {
int numEnemies;
printf("请输入敌人的数量:");
scanf("%d", &numEnemies);
if (numEnemies <= 0) {
printf("敌人数量必须大于 0。\n");
return 0;
}
int* height = (int*)malloc(numEnemies * sizeof(int));
int i;
for (i = 0; i < numEnemies; i++) {
printf("请输入第%d 个敌人的初始高度:", i + 1);
scanf("%d", &height[i]);
}
int bullets = calculateBullets(height, numEnemies);
printf("需要的子弹数量为:%d\n", bullets);
free(height);
return 0;
}