CF1747B - BAN BAN

CF1747B - BAN BAN

题目

BAN BAN - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

  • 题目要求串联n个"BAN",交换任意两个字母让序列不存在"BAN"子序列的最小交换次数。
  • 我们可以很容易想到在B后面不存在A和N或者不存在A、不存在N,时肯定不存在子序列"BAN"。而显然让A或N其中一个字符不在B的后面时交换的次数肯定更少。
  • 把每个"BAN"编号从1到n,我们可以让第1个"BAN"的A和第n"BAN"的N交换,第2个"BAN"的A和第n-1"BAN"的N交换,···,第i个"BAN"的A和第n-i+1"BAN"的N交换···
  • 当n为偶数时刚好两两一对交换完需要n/2次,当n为奇数时最中间的"BAN"和自己交换需要n/2+1次,所以最小交换次数为n/2向上取整,即(n+1)/2次。
  • 我们可以有下面3种交换策略,选其中一种即可:
    • 让B后面没有A,i*3-2(第i个B)和(n-i+1)*3-1(第n-i+1个A)交换。
    • 让B后面没有N,i*3-2(第i个B)和(n-i+1)*3(第n-i+1个N)交换。
    • 让A后面没有N,i*3-1(第i个A)和(n-i+1)*3(第n-i+1个N)交换。

代码

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

// 记录多少个测试用例
int T;

int main() {
    cin >> T;
    // T个测试用例
    while (T--) {
        int n;
        // n个"BAN"串联
        cin >> n;
        // 最少需要交换(n + 1) / 2
        cout << (n + 1) / 2 << endl;
        // 进行(n + 1) / 2次交换,从第1个"BAN"开始
        for (int i = 1; i <= (n + 1) / 2; i++) {
            // 让A后面没有N,i*3-1(第i个A)和(n-i+1)*3(第n-i+1个N)交换。
            cout << 3 * i - 1 << ' ' << (n - i + 1) * 3 << endl;
        }
    }
    return 0;
}

复杂度分析

  • 时间复杂度O(n*T)
  • 空间复杂度O(1)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值