题目传送门:
分析
这道题不难,主要是考思维
首先,或运算有一个性质:
a ∣ a = a a\ |\ a\ =\ a a ∣ a = a
所以,数列和 m m m的关系如下
m m m | a 0 a_0 a0 | a 1 a_1 a1 | a 2 a_2 a2 | a 3 a_3 a3 |
---|---|---|---|---|
0 0 0 | a 0 a_0 a0 | a 1 a_1 a1 | a 2 a_2 a2 | a 3 a_3 a3 |
1 1 1 | a 0 ∣ a 1 a_0|a_1 a0∣a1 | a 0 ∣ a 1 ∣ a 2 a_0|a_1|a_2 a0∣a1∣a2 | a 1 ∣ a 2 ∣ a 3 a_1|a_2|a_3 a1∣a2∣a3 | a 2 ∣ a 3 ∣ a 4 a_2|a_3|a_4 a2∣a3∣a4 |
2 2 2 | a 0 ∣ a 1 ∣ a 2 a_0|a_1|a_2 a0∣a1∣a2 | a 0 ∣ a 1 ∣ a 2 ∣ a 3 a_0|a_1|a_2|a_3 a0∣a1∣a2∣a3 | a 0 ∣ a 1 ∣ a 2 ∣ a 3 ∣ a 4 a_0|a_1|a_2|a_3|a_4 a0∣a1∣a2∣a3∣a4 | a 1 ∣ a 2 ∣ a 3 ∣ a 4 ∣ a 5 a_1|a_2|a_3|a_4|a_5 a1∣a2∣a3∣a4∣a5 |
不难看出, m m m每增大 1 1 1,数列的每一项就会同时向左右扩展
所以,我们可以得出答案:
a i ∣ a i + 1 ∣ . . . ∣ a n + m ( i = m a x ( n − m , 0 ) ) a_{i}|a_{i+1}|...|a_{n+m}(i = max(n-m,0)) ai∣ai+1∣...∣an+m(i=max(n−m,0))
然后我们考虑优化
以一组样例举例:
1145 14
(绝对不是故意的)
则按照公式有:
a n s = 1131 ∣ 1132 ∣ . . . ∣ 1158 ∣ 1159 = ( 10001101011 ) 2 ∣ ( 100010001100 ) 2 ∣ . . . ∣ ( 10010000110 ) 2 ∣ ( 10010000111 ) 2 ans = 1131|1132|...|1158|1159=(100 0110 1011)_2|(100010001100)_2|...|(100 1000 0110)_2|(10010000111)_2 ans=1131∣1132∣...∣1158∣1159=(10001101011)2∣(100010001100)2∣...∣(10010000110)2∣(10010000111)2
观察到, 1131 1131 1131与 1159 1159 1159的二进制有一部分是公共的,并且后面非公共的部分每一位均出现过 1 1 1
同时,我们注意到异或 ( ⊕ ) (\oplus) (⊕)有一个性质
a ⊕ a = 0 a \oplus a = 0 a⊕a=0
所以,我们便可以消去前面公共的部分,然后再求出后面非公共的部分的长度(可以用对数求),构造一个与非公共部分的长度相等的全是 1 1 1的子串,再与 m a x ( a 0 , a n − m ) max(a_0,a_{n-m}) max(a0,an−m)进行或运算即可(当然你也可以选其他的)
代码如下:
//#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,T;
signed mian()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> T;
while(T--)
{
cin >> n >> m;
if(m != 0)
{
int x = (int)(log2(max(0ll,n - m) ^ (n + m))) + 1;
cout << ((n + m) | ((int)pow(2ll,x) - 1)) << "\n";
}
else cout << n << "\n";
}
}
//禁止直接Ctrl C+V!!!
时间复杂度: O ( T ) O(T) O(T)