洛谷

CSP通关之路

#include <iostream>   // 包含输入输出流库
#include <vector>     // 包含向量容器库
#include <algorithm>  // 包含算法库(提供sort函数)
using namespace std;  // 使用标准命名空间,避免重复书写std::

// 类型别名:将long long定义为i64,简化64位整数的书写
// i64直观表示"64-bit integer",增强代码可读性
using i64 = long long;

/**
 * 计算64位整数的前导零个数(Count Leading Zeros)
 * 前导零指二进制表示中,最高位开始连续的0的数量
 * 例如:二进制1001(十进制9)的前导零个数为60(64位表示时)
 * 
 * @param x 待计算的64位整数
 * @return 前导零的个数(x=0时返回64)
 */
int clz(i64 x)
{
    // 从最高位(第63位)开始检查,依次向低位遍历
    for(int i = 0; i != 64; i++)
    {
        // 将x右移(63-i)位,获取从最高位开始的第i位
        // 与1进行按位与运算,判断该位是否为1
        if((x >> (63 - i)) & 1)
            return i;  // 找到第一个为1的位,返回当前计数(前导零个数)
    }
    return 64;  // 如果所有位都是0(x=0),返回64
}

/**
 * 自定义排序比较函数,用于sort函数
 * 排序规则:
 * 1. 先按数字的前导零个数升序排列(前导零少的排在前面)
 * 2. 若前导零个数相同,则按数字本身的大小升序排列
 * 
 * @param x 第一个比较的64位整数
 * @param y 第二个比较的64位整数
 * @return 若x应排在y前面,返回true;否则返回false
 */
bool cmp(i64 x, i64 y)
{
    // 先比较前导零个数
    if(clz(x) == clz(y))
        return x < y;  // 前导零个数相同,按数值升序
    return clz(x) < clz(y);  // 前导零个数不同,按前导零个数升序
}

int main()
{
    int n;  // 存储输入的数字个数
    cin >> n;  // 读取数字个数

    // 创建一个存储i64类型的向量容器,大小为n
    // 注意:原代码中vector<int>会导致类型不匹配,这里修正为vector<i64>
    vector<i64> a(n);

    // 循环读取n个数字,存入向量a中
    for(int i = 0; i < n; i++)
        cin >> a[i];

    // 使用sort函数对向量a进行排序
    // 参数说明:
    // a.begin():排序起始位置(第一个元素)
    // a.end():排序结束位置(最后一个元素的下一位)
    // cmp:自定义的比较函数,指定排序规则
    sort(a.begin(), a.end(), cmp);

    // 循环输出排序后的结果
    // 格式控制:最后一个元素后输出换行,其余元素后输出空格
    for(int i = 0; i < n; i++)
        cout << a[i] << " \n"[i == n - 1];

    return 0;  // 程序正常结束
}