题解:P16258 [DSTOI Round 0] 万分之一的光

· · 题解

题意简述

过程 n 会先把 n 加入序列,再依次执行过程 n-1 和过程 n-2。初始序列含有一个 0

求最终序列中所有相邻两项之和的异或和。每个测试点有多组数据,且 n\le10^{18}

解题思路

记过程 n 自身生成的序列为 P_n,不包含开头额外的 0。再记 P_n 内部所有相邻两项之和的异或和为 X_n

由递归定义可知,P_n 的第一项为 n,最后一项始终为 1。当 n\ge3 时,序列满足:

P_n=[n]+P_{n-1}+P_{n-2}

除了两个子序列内部的贡献,还要计算两处拼接位置。nP_{n-1} 的首项之和为 2n-1P_{n-1} 的末项与 P_{n-2} 的首项之和为 n-1。因此:

X_n=X_{n-1}\mathbin{\operatorname{xor}}X_{n-2}\mathbin{\operatorname{xor}}(2n-1)\mathbin{\operatorname{xor}}(n-1)

X_{n-1} 的同类递推式代入,上式中的两个 X_{n-2} 会相互抵消,得到:

X_n=X_{n-3}\mathbin{\operatorname{xor}}(2n-1)\mathbin{\operatorname{xor}}(2n-3)\mathbin{\operatorname{xor}}(n-1)\mathbin{\operatorname{xor}}(n-2)

k=n-1,并令 l=\operatorname{lowbit}(k)。二进制中,kk-1 从最低位 1 开始的后缀全部相反,所以:

k\mathbin{\operatorname{xor}}(k-1)=2l-1

同时,2k+12k-1 的最低位都是 1,去掉这一位后分别为 kk-1。于是:

\begin{aligned} & (2k+1)\mathbin{\operatorname{xor}}(2k-1)\mathbin{\operatorname{xor}}k\mathbin{\operatorname{xor}}(k-1) \\ & =(4l-2)\mathbin{\operatorname{xor}}(2l-1) \\ & =2l+1 \end{aligned}

递推式因而化为:

X_n=X_{n-3}\mathbin{\operatorname{xor}}\left(2\operatorname{lowbit}(n-1)+1\right)

直接计算可得 X_1=0X_2=3X_3=4。将递推式按下标每次减少 3 展开,可以统一写成:

X_n=[3\mid n]\mathbin{\operatorname{xor}}\mathop{\operatorname{xor}}_{\substack{1\le k<n\\k\equiv n-1\pmod 3}}\left(2\operatorname{lowbit}(k)+1\right)

其中 [3\mid n]3 整除 n 时为 1,否则为 0。开头额外的 0P_n 的第一项 n 还产生一个贡献 n,所以最终答案为 n\mathbin{\operatorname{xor}}X_n

下面快速计算式中的异或和。

w=n-1。对每个非负整数 i,记 r_i 为满足以下条件的 k 的数量:

r_i=\#\{k\mid 1\le k\le w, k\equiv w\pmod 3, 2^i\mid k\}

最低位恰为 2^i 的数共有 r_i-r_{i+1} 个。若只保留这些数量的奇偶性,所有最低位贡献可以整理为:

\begin{aligned} & \mathop{\operatorname{xor}}_i[(r_i-r_{i+1})\bmod2]\left(2^{i+1}+1\right) \\ & =\mathop{\operatorname{xor}}_i[r_i\bmod2]\left(2^{i+1}\mathbin{\operatorname{xor}}2^i\right) \\ & =\mathop{\operatorname{xor}}_i[r_i\bmod2]\left(3\cdot2^i\right) \end{aligned}

因此,只需分别求出每个 r_i 的奇偶性。

k=2^iq,并设 m=\lfloor w/2^i\rfloor。因为 2^i 在模 3 意义下的逆元随 i 的奇偶性交替为 1,2,所以 q 应满足:

q\equiv \rho_i\pmod 3

其中:

\rho_i= \begin{cases} w\bmod3 & i\text{ 为偶数} \\ 2w\bmod3 & i\text{ 为奇数} \end{cases}

区间 1\le q\le m 中符合条件的数有:

r_i= \begin{cases} \left\lfloor\frac{m}{3}\right\rfloor & \rho_i=0 \\ \left\lfloor\frac{m+3-\rho_i}{3}\right\rfloor & \rho_i>0 \end{cases}

由于 n<2^{60},枚举 i=0,1,\dots,59 即可。若 r_i 为奇数,就把 3\cdot2^i 异或进答案。

单组数据的时间复杂度为 O(\log n),空间复杂度为 O(1)

参考代码

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

using ull=unsigned long long;
ull solve(ull n)
{
    ull w=n-1;
    ull ans=n;
    if(n%3==0)ans^=1;
    for(int i=0;i<60;i++)
    {
        ull m=w>>i;
        int r=w%3*(i&1?2:1)%3;
        ull cnt;
        if(r==0)cnt=m/3;
        else cnt=(m+3-r)/3;
        if(cnt&1)ans^=3ull<<i;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin>>T;
    while(T--)
    {
        ull n;
        cin>>n;
        cout<<solve(n)<<'\n';
    }
    return 0;
}