题解 | 最通俗易懂,最详细的题解

小苯的最短路

https://www.nowcoder.com/practice/2130991f48ae48b588398ba5842c7ec0

思路:看一眼数据,回答最多O( \log n),但很显然这题要求我们用O( 1),也就是推一个式子。

由于必须O(1)回答,所以对于1到j的最短路径,一定是直接边

结论1:两个不同的正整数异或结果一定非负,既i\oplus j >1 (i\ne j)

已知1\oplus j可以让原本偶数+1,奇数-1,

假设有中间转点k,则其路径至少是

1 \oplus k + k\oplus j=k+k \oplus j

k>j,也就是至少 k\ge j+1,容易发现无论j是奇数还是偶数,都不比这个方案数劣。

k<j,根据异或结果不小于差值可以证明,这里不展开

现在分析结果的输出,由于d_i=(1\oplus i),所以结果是

S=(1\oplus 2) \oplus (1\oplus 3)\oplus \cdots \oplus (1 \oplus n)

考虑n是奇数的情况

除了1每一项都有个1跟他异或,所以有偶数个1,由于结合律和分配率,我们可以把偶数个1先进行异或,由于自己和自己异或一定得0,而0和任何数异或都得任何数,所以最终就变成

S=2\oplus 3\oplus 4\oplus \cdots \oplus n

若x是奇数,则x和x-1异或一定为1(因为x和x-1只在末尾有不同,一个是0,一个是1),这n-1个数如果划分为2组

假设可以划分成偶数个组,形如

S=(2\oplus 3)\oplus(4\oplus 5)\oplus (6\oplus 7)\oplus (8\oplus 9)=1\oplus 1\oplus 1\oplus 1=0\oplus 0=0

同理,如果可以划分为奇数个组,最后就是0异或上1,变成1,形如

S=(2⊕3)⊕(4⊕5)⊕(6⊕7)=1⊕1⊕1=0⊕1=1 

考虑n是偶数的情况:

若n是偶数,则有奇数个1,把偶数个1先合并为0,只剩下一个1,最后形如

1 \oplus 2\oplus 3\oplus \cdots \oplus n

这一特殊形式肯定有公式,但如果考场上遇到了不会做没关系,可以试着推一推,还是想刚才那样。

如果把一个奇数和比他小1的数进行每2个每2个的分,既n-2肯定是偶数,然后还是像刚刚奇数那样分析,如果n-2进行2个2个的划分,如果分出偶数组,也就是(n-2)/2也是偶数,那么恰好是这样的一个情况

1⊕ (2⊕3)⊕(4⊕5)⊕6=1⊕6=7

既(n-2)%2==0时,输出n+1,反之,如果是奇数组,会出现

1⊕(2⊕3)⊕4=1⊕1⊕4=0⊕4=4

因此我们的策略是:

当n是奇数时,把偶数个1全部小曲,此时剩下2到n这n-1个数,进行分组,若能分为奇数组,则为1,若能分为偶数组,则为0

当n是偶数时,此时计算1异或到n,若1和n之间能划分为奇数组,则为n,否则为n+1

如此,我们就完成了这道题,这道题如果不知道结论,利用异或的几个重要性质可以很快推出来,当然开头的证明大部分是猜的,因为O(1)的回答不可能允许我们再去找任何最短路,唯一的可能就是1到j的最短路就是1异或上j

#include <iostream>
using namespace std;

int main() {
    ios::sync_with_stdio(false),cin.tie(0);
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        if(n&1){
            n--;
            n/=2;
            if(n&1)cout<<1;
            else cout<<0;
        }
        else{
            int t=n;
            n-=2;
            n/=2;
            if(n&1)cout<<t;
            else cout<<t+1;
        }
        
        cout<<"\n";
    }
}
// 64 位输出请用 printf("%lld")
全部评论
另外,通过这次的分析,还可以学会这道题的另外的一版本,如果S改为了d1+d2+d3,既(1⊕2)+(1⊕3)+...的形式 由于异或上1会让奇数-1,偶数+1,每2项的和不变,若是偶数项 (1⊕2)+(1⊕3)+(1⊕4)+(1⊕5)=(2+1)+(3-1)+(4+1)+(5-1)=2+3+4+5=S[5]-1 若是奇数项 (1⊕2)+(1⊕3)+(1⊕4)=(2+1)+(3-1)+(4+1)=2+3+4+1=S[4] 即答案为S[n]-1+(n&1)
点赞 回复 分享
发布于 01-28 01:56 广东

相关推荐

评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务