cf1534E. Lost Array

题目描述

题解

如果每个元素被都访问到奇数次则可以知道异或和,否则不知道。

就相当于给定一些向量的话,能否线性表出一个向量,其中表出方式为异或。

因此我们考虑如果目前有 $i$ 个元素为奇数次被访问了,把这 $i$ 个元素放在一个集合,每次在这个集合里选出 $j$ 个元素踢出去,然后再从集合外选 $k-j$ 个元素放进去。

因此只要 $\text{bfs}$ 这个过程即可。

效率: $O(nk)$ 。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,k,f[N],g[N],s;
queue<int>p,q;
int main(){
    scanf("%d%d",&n,&k);
    q.push(k);f[k]=1;
    for (;!q.empty();){
        int u=q.front();q.pop();
        for (int i=0,v;i<=k && i<=u;i++){
            if (k-i>n-u) continue;
            v=u-i+k-i;if (v && v<=n && !f[v])
                q.push(v),f[v]=f[u]+1,g[v]=u;
        }
    }
    if (!f[n]){
        puts("-1");return 0;
    }
    for (int i=1;i<=n;i++) q.push(i);
    for (int i=n,j,u;i;i=g[i]){
        u=g[i];j=(u+k-i)>>1;
        printf("?");
        for (int l=0;l<k-j;l++)
            printf(" %d",q.front()),
            p.push(q.front()),q.pop();
        for (int l=0;l<j;l++)
            printf(" %d",p.front()),
            q.push(p.front()),p.pop();
        puts("");fflush(stdout);
        scanf("%d",&u);s^=u;
    }
    printf("! %d\n",s);fflush(stdout);
    return 0;
}

 

posted @ 2021-11-07 21:00  xjqxjq  阅读(27)  评论(0编辑  收藏  举报