Loading

6.28 CW 模拟赛 T1. 致敬传奇捆绑测试题目

前言

你说的对, 但是系统卡顿为啥可以用更新显卡驱动解决啊, 太猎奇了

心态, 停滞, 策略
哎我管你这那的

思路

首先考虑这个问题
要求任意一个数之前的前缀和大于这个数的排列中, 字典序最小的
打个表看下性质

发现性质最轻松的一集, 不难发现 \(a_1\)\([1]\), \(a_2\)\([2, 1]\), 此后 \(a_l = [3, 1, 2, 4, 5 \cdots l - 1, l]\), 不可能存在更小的 \(a_l\)


现在考虑原问题
我们现在要求

\[ \begin{align*} & \bigoplus_{l = 1}^{n} \bigoplus_{i = 1}^{l} (a_{l, i} + i) \\ =& \bigoplus_{l = 4}^{n} \left(2 \oplus \bigoplus_{i = 4}^{l} 2i\right) \\ =& \Big([2 \nmid (n - 4 + 1)] \times 2\Big) \oplus \bigoplus_{l = 4}^{n}\bigoplus_{i = 4}^{l} 2i \\ =& \Big([2 \nmid (n - 4 + 1)] \times 2\Big) \oplus \bigoplus_{i = 4}^{n} \Big([2 \nmid (n - i + 1)] \times 2i\Big) \end{align*} \]

\(n \leq 10^{18}\), 还不够

考虑异或操作的性质, 不难发现我们可以拆位计算, 现在的问题是

\[2n \oplus 2(n - 2) \oplus \cdots \oplus 4/5 \]

中, 位 \(i\) 出现了多少次

一个数 \(x\) 的位 \(i\)\(1\), 当且仅当 \(\lfloor x/2^i \rfloor\) 为奇数
这个咋统计啊
考虑另外一种性质

不难发现类似十进制转二进制的方法, 我们每次只需要考虑当前的奇偶性, 然后对它除以 \(2\) 向下取整即可
依据这个性质, 不难发现会以 \(-1-2-4-8-\cdots\) 的形式出现数字变为 \(0\), 总的轮数显然是 \(\log n\) 级别的, 完全可以接受
我们大概画一个图来展现这个过程
pVncNzd.png


pVncYJe.png

每次点的数量和奇偶点的数量都很好计算, 按需统计异或和即可

代码
#include <bits/stdc++.h>
#define int long long
#define ever ;;

signed main() {
    int n; scanf("%lld", &n);
    int res = 0;
    if (n == 1) { printf("2"); return 0; }
    if (n == 2) { printf("2"); return 0; }
    if ((n - 3) % 2) res = 2;
    int ans = 0;
    // for (int i = 4; i <= n; i++) {
    //     if ((n - i + 1) % 2) res ^= 2 * i;
    // }
    int begin = (n % 2) ? 5 : 4;

    int len = n / 2 - 1;
    int turn = -1;
    int del = 0; // 打个补丁, 懒了
    for (ever) {
        // std::cout << len << '\n';
        if (len <= 0) { ans ^= (del % 2) << (turn + 2); break; }
        if (turn == -1) { if (begin % 2) ans ^= ((len % 2) << (turn + 2)); }
        else {
            int cir = 1ll << turn, num = len / cir;
            int time = (num / 2 * cir) + ((num % 2 == 1) * (len % cir)) + del;
            ans ^= (time % 2) << (turn + 2);
        }
        turn++;
        if (turn) del = std::min(1ll << turn, len), len -= (1ll << turn);
    }
    printf("%lld", res ^ ans);

    return 0;
}

总结

做出这个题比较关键的一点是打表?
大概就是你啥都不会的时候一定要动起来

异或特有的拆位, 不管了

posted @ 2025-06-30 07:45  Yorg  阅读(9)  评论(0)    收藏  举报