题目大意:
这是一道通信题。
A接受n,k个位置,和long long类型的x。返回一个长为n的字符串,满足那k个位置必须是’0’,其余可以是’0’或者’1’。B接受A返回的字符串,返回x。
题解:
场上(去场上的路上)想到了一个做法,随机一个每个数值都是64位非负整数的常数列,然后A看x能用其中哪些数字异或得到(那k个位置对应的数字不能使用),将s的这些位置设为1.然后B根据s随便异或一下就可以了。这个过程相当于是用n-k>=110个数生成一个64位的满的线性基的概率,这个显然轻松满秩。
然而std还有一个构造解,考虑每三位视为一组。
若这一组中有至少两个位置被禁掉了,就不传输信息(000)。
否则若有一个位置被禁掉了,那么如果要传输的是1,那么s对应+=001或者110(取决于哪一个位置被禁掉了);否则如果要传输的是0,若第一位没有被禁掉,就s+=100。但是若第一位被禁掉了,那么用010和011分别表示00和01;最后三位都没被禁掉,用101和111表示10和11即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
#define N 200
#define M 64
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
struct RAND{
ull x;RAND() { init(); } inline int init() { return x=998244353,0; }
inline ull operator()() { return (x=(((x^1000000007)*998244353)+19260817)^(x<<13)^(x>>3)); }
};static RAND rnd;
namespace Alice_space{
static ull val[N];
struct LB{
ull p[M+10],res[M+10];int pos[M+10];
inline int init()
{
memset(p,0,sizeof p),
memset(pos,0,sizeof pos),
memset(res,0,sizeof res);
return 0;
}
inline int ins(ull x,int ps)
{
ull r=0;
for(int i=M-1;i>=0;i--)
if((x>>i)&1)
{
r^=res[i];
if(!p[i]) res[i]=r^(1ull<<i),p[i]=x,pos[i]=ps;
x^=p[i];
}
return 0;
}
inline string solve(ull x,int n)
{
string ans;ans.resize(n);
rep(i,0,n-1) ans[i]='0';ull r=0;
for(int i=M-1;i>=0;i--) if((x>>i)&1)
assert(p[i]),x^=p[i],r^=res[i];
assert(x==0);
rep(i,0,M-1) if((r>>i)&1) ans[pos[i]]='1';
return ans;
}
};static LB lb;static int ban[N];
static string solve(int n,vector<int> p,ull x)
{
rnd.init(),lb.init();rep(i,0,n-1) ban[i]=0;
Rep(i,p) ban[p[i]]=1;rep(i,0,n-1) val[i]=rnd();
rep(i,0,n-1) if(!ban[i]) lb.ins(val[i],i);
return lb.solve(x,n);
}
}
string alice(int n,const vector<int> &p,lint x)
{
return Alice_space::solve(n,p,x);
}
namespace Bob_space{
static ull val[N];
inline lint solve(string s)
{
int n=(int)s.length();ull ans=0;
rnd.init();rep(i,0,n-1) val[i]=rnd();
rep(i,0,n-1) if(s[i]=='1') ans^=val[i];
return (lint)ans;
}
}
lint bob(const string &s)
{
return Bob_space::solve(s);
}