题解 | #活着的证据#

踩不出足迹

https://ac.nowcoder.com/acm/contest/11178/C

【C.踩不出足迹】题解
看见其他大佬的题解,都是得出了一个简单的结论。我来讲讲我的。
我们分开考虑0~k-1位二进制数,想要结果最大,最终运算出来的结果第k-1位必然为1,我们任取一种运算方式(比如在代码中,我让前n-1个数字异或,判断和最后一个数字是同或还是异或),使得k-1位为1。
emm之后我们考虑其他位的数(0 ~ k-2) ,若按照上述任取的运算方式,计算出的答案为0,我们考虑在不影响高位的情况下,修改运算方式,使得该位变为1. 事实证明,这是无法完成的。因为若要修改一位上的数⇔修改奇数个运算符号,因此修改该位的运算结果必然会影响到高位。

所以算法很简单,只需要根据第k-1位确定出运算方式,然后每位按照同样的方式计算即可,注意用unsigned long long

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef  long long ll;
const int N = 2000010 ,M = 1000010,mod = 998244353;
int n,m,d,k;
ull a[N],jie[100];
int res[N];
signed main()
{
    jie[0] = 1;
    for(int i=1;i<=63;i++) jie[i] = jie[i-1]*2;
    cin>>n>>k;k--;
    for(int i=1;i<=n;i++) scanf("%llu",&a[i]);
    int z = 0;
    for(int i=1;i<n;i++)
        z^=(a[i]>>k&1);
    bool f = z==(a[n]>>k&1);//确定最后一个数是异或还是同或,若f位true则为同或 
    ull res = 0;
    for(int i=k;i>=0;i--)//按位 运算即可 
    {
        int z = 0;
        for(int j=1;j<n;j++)
            z^=(a[j]>>i&1);

        if(!f) z^=(a[n]>>i&1);//异或 
        else
            z = z==(a[n]>>i&1);//同或 
        if(z)
            res+=jie[i];
    }
    cout<<res;
    return 0;
}
全部评论

相关推荐

3 收藏 评论
分享
牛客网
牛客企业服务