题解:CF2056F2 Xor of Median (Hard Version)
引理
若
引理 1:
引理 2:
引理 3:
引理 4:
此处只证明引理 3。首先
F1 题解
首先,可以枚举
记
这里简单解释一下,首先
这样 F1 就做完了,使用引理 1、引理 2 计算,时间复杂度
#include<bits/stdc++.h>
using namespace std;
int t,k,n,m,ans;
char n2[200005];
int main() {
scanf("%d",&t);
while(t--) {
scanf("%d%d%s",&k,&m,n2);
n=0;
for(int i=0; i<k; i++) n+=(n2[i]=='1');
ans=0;
for(int y=1; y<=min(n,m); y++)
for(int x=0; x<m; x++)
if(((y-1)|x)==x && ((n-y)&((y-1)/2))==0)
ans^=x;
printf("%d\n",ans);
}
return 0;
}
F2 题解
记:
答案就是
我们分成两个部分进行优化,第一部分是计算
第一部分的可以使用 sosdp。
注意到
第二部分,由引理 4 可以简单计算。
#include<bits/stdc++.h>
using namespace std;
int t,k,n,m,N,ans;
char n2[200005];
int f[300005];
int main() {
scanf("%d",&t);
while(t--) {
scanf("%d%d%s",&k,&m,n2);
n=0;
for(int i=0; i<k; i++) n+=(n2[i]=='1');
ans=0;
int N=0;
while((1<<N)<=min(n,m)) N++;
for(int j=0; j<(1<<N); j++) f[j]=(j<n && j<m && (((n-j-1)&(j/2))==0));
for(int i=0; i<N; i++)
for(int j=0; j<(1<<N); j++)
if(j&(1<<i))
f[j]^=f[j^(1<<i)];
// 分块计算
int t=0, cnt=0;
for(int x=0; x<(1<<N); x++)
if(f[x])
t^=x, cnt++;
int x=0, bk=m>>N;
if(bk&1) ans^=t;
if(cnt&1) {
// 0 xor 1 xor 2 xor ... xor bk-1
switch((bk-1)&3) {
case 0: {
ans^=((bk-1)>>2<<2)<<N;
break;
}
case 1: {
ans^=1<<N;
break;
}
case 2: {
ans^=(((bk-1)>>2<<2)+3)<<N;
break;
}
}
}
for(int x=((m>>N)<<N); x<m; x++) ans^=x*f[x%(1<<N)];
printf("%d\n",ans);
}
return 0;
}