【2024蓝桥杯/C++/B组/逆序对期望】

问题

代码

#include<bits/stdc++.h>
using namespace std;

// 定义变量n
int n;
// 定义计数器cnt,用于统计组合数量
int cnt;
// 定义答案变量ans
int ans;
// 定义一个数组CASE,用来存储每个位置上的数值
int CASE[60];

// 函数cal()用于计算每一种情况下逆序对的数量
void cal()
{
    // 双层循环遍历每一个可能的逆序对
    for(int i = 1; i <= n; i++)
    {
        for(int j = i+1; j <= n; j++)
        {
            // 如果找到一个逆序对,则增加逆序对总数
            if(CASE[i] > CASE[j]) ans++;
        }
    }
}
// 主函数main()
int main()
{
    // 初始化n为51
    n = 51;

    // 使用四层循环枚举所有可能的两组不同的索引
    for(int d11 = 1; d11 <= n; d11++)
        for(int d12 = d11+1; d12 <= n; d12++)
            for(int d21 = 1; d21 <= n; d21++)
                for(int d22 = d21+1; d22 <= n; d22++)
                {
                    // 每进入一次内层循环,计数器cnt加一
                    cnt++;
                    // 将数组CASE初始化为1到n的序列
                    for(int i = 1; i <= n; i++) CASE[i] = i;
                    // 交换CASE中索引d11和d12的值
                    swap(CASE[d11], CASE[d12]);
                    // 交换CASE中索引d21和d22的值
                    swap(CASE[d21], CASE[d22]);

                    // 调用cal()计算当前序列下的逆序对数量
                    cal();
                }
    // 输出逆序对总数除以组合数量的平均值,保留四位小数
    cout << setprecision(4) << (double)ans / cnt;
}
#include<bits/stdc++.h>
using namespace std;

// 定义全局变量
int n;
int cnt;
int ans;
int CASE[60];
int M[60];

// 合并排序的合并函数
void merge(int l, int r)
{
    // 如果左边界小于右边界,递归划分数组
    if(l < r)
    {
        // 计算中间位置
        int mid = (l+r) >> 1;
        
        // 递归地对左右两边进行排序
        merge(l, mid);
        merge(mid+1, r);

        // 初始化临时指针和两个子数组的指针
        int tmp = l, i = l, j = mid+1;
        
        // 当两个子数组都有元素时
        while(i <= mid && j <= r)
        {
            // 如果左侧的数大于右侧的数
            if(CASE[i] > CASE[j])
            {   
                // 更新逆序对数量
                ans += mid - i + 1;
                
                // 将较小的元素放入辅助数组
                M[tmp++] = CASE[j++];
            }
            // 否则将左侧的元素放入辅助数组
            else M[tmp++] = CASE[i++];
        } 

        // 如果左侧还有剩余元素,依次放入辅助数组
        while(i <= mid) M[tmp++] = CASE[i++];
        
        // 如果右侧还有剩余元素,依次放入辅助数组
        while(j <= r) M[tmp++] = CASE[j++];

        // 将排序后的辅助数组复制回原数组
        memcpy(CASE+l, M+l, sizeof(int)*(r-l+1));
    }

    
}

// 主函数
int main()
{
    // 初始化n为51
    n = 51;

    // 枚举所有可能的两对不同的索引
    for(int d11 = 1; d11 <= n; d11++)
        for(int d12 = d11+1; d12 <= n; d12++)
            for(int d21 = 1; d21 <= n; d21++)
                for(int d22 = d21+1; d22 <= n; d22++)
                {
                    // 对每一对索引计数
                    cnt++;
                    
                    // 初始化数组CASE为1到n
                    for(int i = 1; i <= n; i++) CASE[i] = i;
                    
                    // 交换两对索引对应的元素
                    swap(CASE[d11], CASE[d12]);
                    swap(CASE[d21], CASE[d22]);

                    // 使用归并排序计算逆序对的数量
                    merge(1,n);
                }

    // 输出平均逆序对数量
    cout << setprecision(4) << (double)ans / cnt;
}

疑惑

在编写代码时,我将

// 将排序后的辅助数组复制回原数组
memcpy(CASE+l, M+l, sizeof(int)*(r-l+1));

放到l < r的判断体之外,结果输出为0,查验发现CASE[i] > CASE[j]判断体不会进入。

一开始我以为是l > r导致memcpy出现错误

于是我换成

for(int i = l; i <= r; i++)
{
    CASE[i] = M[i];
}

但是情况依旧。

解答

分到单个元素的时候不应该覆盖。结果覆盖了。

倒数第二层的比较就全是0和0的了,难怪进不去第一个判断体。

上面也全废了,ans=0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值