题解 P6599 【「EZEC-2」异或】

· · 题解

考场心路历程

由于是unrated比赛所以只写了个签到题

5min写完了,难度建议橙/黄

IEE出的题质量还不错/cy

思路简述

首先考虑给定 l 个数,求那个式子的值的情况。

由于位运算位与位之间互不干扰,我们可以考虑按位分析,再计算每一位可以给总答案的贡献。

于是对于每一位,问题转化成了给定 n01,求那个式子的值。

注意到以下的性质:

  1. 这些 01 两两的 xor 值只能是 01
  2. 上一条性质中取 1 的情况为一个 0 异或一个 1
  3. 对答案的贡献就是取 1 的情况乘以这一位的位值。

显然这一位的贡献就是 2^k\times x\times(l-x) ,其中 2^k 代表所在的二进制位,x 代表这一位 1 (或者 0 ) 的数量,总答案即为各位的贡献和。

那么如果告诉你这些数的最大值,怎么最大化那个式子呢?

还是先看每一位的情况

在上面的公式中,对于每一位, 2^k 是给定的,那么问题就是 x\times(l-x) 如何最大化?

小学奥数基础知识: x=\frac{l}{2}(2\mid l)x=\frac{(l\pm1)}{2} (2\nmid l) 时取到。

所以我们要保证每一位的 1 数量尽可能靠近 \frac{l}{2}

简单的讨论之后发现每一位都可以取到最大值。

构造证明:

p 为不大于 n 的最大 2 的自然数次幂数,则

~~然后就做完了~~ 恭喜你,WA了(((((( 注意特判 $n=1$ ,因为 $p-1=0$ 取不到,手模一下发现直接输出 $0$ 即可。 ## Code ``` #include<bits/stdc++.h> using namespace std; inline int read() { int f=1,num=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1; ch=getchar();} while(isdigit(ch)) num=(num<<1)+(num<<3)+ch-'0',ch=getchar(); return num*f; } inline long long readll() { long long f=1,num=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1; ch=getchar();} while(isdigit(ch)) num=(num<<1)+(num<<3)+ch-'0',ch=getchar(); return num*f; } int main() { int T=read(); ++T; while(--T) { long long x=readll(),y=readll(),t=y>>1; if(x==1) { puts("0"); continue; } long long now=1LL<<40,res=0; while(now) { now>>=1; if(x<now) continue; res+=now*t*(y-t); } printf("%lld\n",res%1000000007LL); } return 0; } ```