题解 密码
很有趣的一道交互题
首先通过加入一些特征码来标记有用信息可以拿到 45pts
然后正解对于不会线性基的我来说较难想到
- 通信题可以考虑通过同一个随机数种子来传递信息
考虑利用线性基(以下复制题解)
两个程序用同一个随机种子随机生成m个n位01串
程序A输出的这个m位01串的每一位代表这m个01串的每一个参不参与xor
程序A把自由的那m-k个01串做线性基,由于m-k>=n+50,满秩的概率非常高(约为 \(1-2^{-50}\))
然后为了表示出输入串xor上那些定死的串,只需要在线性基上跑即可
程序B的任务很简单,就是作一番xor
用 bitset 优化,复杂度 \(O(n^3/w)\)
点击查看代码
#include <bits/stdc++.h>
#include "password.h"
using namespace std;
#define INF 0x3f3f3f3f
#define fir first
#define sec second
namespace task1{
int cnt[110][2];
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
int tim=m/n, pos=0;
for (int i=1; i<=tim; ++i)
for (int j=0; j<n; ++j)
ans[pos++]=a[j];
while (pos<m) ans[pos++]='0';
for (int j=0; j<m; ++j) if (b[j]!='?') ans[j]=b[j];
}
void decoder(int n, int m, const char* a, char* ans) {
for (int i=0; i<n; ++i) cnt[i][0]=cnt[i][1]=0;
int tim=m/n, pos=0;
for (int i=1; i<=tim; ++i)
for (int j=0; j<n; ++j)
++cnt[j][a[pos++]-'0'];
for (int i=0; i<n; ++i) {
if (cnt[i][0]>cnt[i][1]) ans[i]='0';
else ans[i]='1';
}
// cout<<"ans: "; for (int i=0; i<n; ++i) cout<<ans[i]<<' '; cout<<endl;
// printf("ans: "); for (int i=0; i<n; ++i) printf("%c", ans[i]); printf("\n");
}
}
namespace task2{
int cnt[110][2];
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
int tim=m/n, pos=0;
for (int i=1; i<=tim; ++i) {
for (int j=0; j<n; ++j)
ans[pos++]=a[j];
if (i&1) reverse(ans+i*tim, ans+i*tim+1);
}
while (pos<m) ans[pos++]='0';
for (int j=0; j<m; ++j) if (b[j]!='?') ans[j]=b[j];
}
void decoder(int n, int m, const char* a, char* ans) {
for (int i=0; i<n; ++i) cnt[i][0]=cnt[i][1]=0;
int tim=m/n, pos=0;
for (int i=1; i<=tim; ++i) {
if (i&1) reverse(ans+i*tim, ans+i*tim+1);
for (int j=0; j<n; ++j)
++cnt[j][a[pos++]-'0'];
}
for (int i=0; i<n; ++i) {
if (cnt[i][0]>cnt[i][1]) ans[i]='0';
else ans[i]='1';
}
// cout<<"ans: "; for (int i=0; i<n; ++i) cout<<ans[i]<<' '; cout<<endl;
// printf("ans: "); for (int i=0; i<n; ++i) printf("%c", ans[i]); printf("\n");
}
}
namespace task3{
const char mask[]="111111011", len=9;
int pos1=0, pos2=0, tm;
bool disable(int pos2, const char* b) {
for (int i=pos2+1; i<=pos2+len+1; ++i) if (b[i]!='?') return 1;
return 0;
}
int findnxt(int now, const char* b) {
while (now<tm) {
if (b[now]!='?') return now;
++now;
}
return INF;
}
void putmask(const char* b, char* ans) {
int lst=findnxt(pos2, b), r=lst+len+1;
while (findnxt(lst+1, b)-r<=len) lst=findnxt(lst+1, b), r=lst+len+1;
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
while (pos2<=lst) ans[pos2++]='0';
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
}
void init(char* ans, const char* b) {
while (findnxt(pos2, b)-pos2<=2*len) pos2=findnxt(pos2, b)+1;
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
}
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
tm=m;
init(ans, b);
// cout<<"pos2: "<<pos2<<endl;
// printf("%d\n", pos2);
while (pos1<n) {
if (disable(pos2, b)) putmask(b, ans);
ans[pos2++]=a[pos1++];
}
for (int i=0; i<m; ++i)
if (b[i]!='?') ans[i]=b[i];
else {
if (ans[i]!='0'&&ans[i]!='1') ans[i]='0';
}
// assert(pos2<=m);
// cout<<"ans: "; for (int i=0; i<pos2; ++i) cout<<ans[i]; cout<<endl;
}
bool ismask(int pos, const char* a) {
for (int i=0; i<len; ++i) if (a[pos+i]!=mask[i]) return 0;
return 1;
}
void decoder(int n, int m, const char* a, char* ans) {
int pos1=0, pos2=0;
while (!ismask(pos2, a)) ++pos2;
pos2+=len;
while (pos1<n) {
if (ismask(pos2, a)) {
pos2+=len+1;
while (!ismask(pos2, a)) ++pos2;
pos2+=len;
}
ans[pos1++]=a[pos2++];
}
// assert(pos2<=m);
// assert(pos1==n);
}
}
namespace task5{
const char mask[]="11111010101011100101", len=20;
int pos1=0, pos2=0, tm;
bool disable(int pos2, const char* b) {
for (int i=pos2+1; i<=pos2+len+1; ++i) if (b[i]!='?') return 1;
return 0;
}
int findnxt(int now, const char* b) {
while (now<tm) {
if (b[now]!='?') return now;
++now;
}
return INF;
}
void putmask(const char* b, char* ans) {
int lst=findnxt(pos2, b), r=lst+len+1;
while (findnxt(lst+1, b)-r<=len) lst=findnxt(lst+1, b), r=lst+len+1;
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
while (pos2<=lst) ans[pos2++]='0';
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
}
void init(char* ans, const char* b) {
while (findnxt(pos2, b)-pos2<=2*len) pos2=findnxt(pos2, b)+1;
for (int i=0; i<len; ++i) ans[pos2++]=mask[i];
}
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
tm=m;
init(ans, b);
// cout<<"pos2: "<<pos2<<endl;
// printf("%d\n", pos2);
while (pos1<n) {
if (disable(pos2, b)) putmask(b, ans);
ans[pos2++]=a[pos1++];
}
for (int i=0; i<m; ++i)
if (b[i]!='?') ans[i]=b[i];
else {
if (ans[i]!='0'&&ans[i]!='1') ans[i]='0';
}
// assert(pos2<=m);
// cout<<"ans: "; for (int i=0; i<pos2; ++i) cout<<ans[i]; cout<<endl;
}
bool ismask(int pos, const char* a) {
for (int i=0; i<len; ++i) if (a[pos+i]!=mask[i]) return 0;
return 1;
}
void decoder(int n, int m, const char* a, char* ans) {
int pos1=0, pos2=0;
while (!ismask(pos2, a)) ++pos2;
pos2+=len;
while (pos1<n) {
if (ismask(pos2, a)) {
pos2+=len+1;
while (!ismask(pos2, a)) ++pos2;
pos2+=len;
}
ans[pos1++]=a[pos2++];
}
// assert(pos2<=m);
// assert(pos1==n);
}
}
namespace task{
int base[2010], cnt;
bitset<2010> s[2100], form[2100], bkp[2100], tem;
void insert(int i) {
form[i][i]=1;
for (int j=s[i]._Find_first(); j<2010; j=s[i]._Find_next(j))
if (base[j]==-1) {base[j]=i; ++cnt; /*cerr<<"j: "<<j<<endl;*/ return ;}
else s[i]^=s[base[j]], form[i]^=form[base[j]];
}
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
mt19937 rand(1206927149);
//cerr<<"m: "<<m<<endl;
tem.reset();
memset(base, -1, sizeof(base)); cnt=0;
for (int i=0; i<n; ++i) if (a[i]=='1') tem[i]=1;
for (int i=0; i<m; ++i) for (int j=0; j<n; ++j) s[i][j]=rand()&1;
for (int i=0; i<m; ++i) bkp[i]=s[i];
//for (int i=0; i<m; ++i) cerr<<s[i]<<endl;
for (int i=0; i<m; ++i)
if (b[i]=='1') tem^=s[i], ans[i]='1';
else if (b[i]=='?') insert(i), ans[i]='0';
else ans[i]='0';
//cerr<<"n: "<<n<<endl;
//cerr<<"cnt: "<<cnt<<endl;
assert(cnt==n);
//cerr<<"tem: "<<tem<<endl;
for (int i=tem._Find_first(); i<2010; i=tem._Find_next(i))
for (int j=form[base[i]]._Find_first(); j<2010; j=form[base[i]]._Find_next(j))
tem^=bkp[j], ans[j]^=1;
//cerr<<"tem: "<<tem<<endl;
//for (int i=0; i<m; ++i) cerr<<ans[i]; cerr<<endl;
}
void decoder(int n, int m, const char* a, char* ans) {
mt19937 rand(1206927149);
tem.reset();
for (int i=0; i<m; ++i) for (int j=0; j<n; ++j) s[i][j]=rand()&1;
for (int i=0; i<m; ++i) if (a[i]=='1') tem^=s[i];
for (int i=0; i<n; ++i) ans[i]=tem[i]?'1':'0';
//for (int i=0; i<n; ++i) cerr<<ans[i]; cerr<<endl;
}
}
void encoder(int n, int m, int k, const char* a, const char* b, char* ans) {
// if (m==70) task1::encoder(n, m, k, a, b, ans);
// else if (m==100) task2::encoder(n, m, k, a, b, ans);
// else if (m==1500) task5::encoder(n, m, k, a, b, ans);
// else if (m==300) task3::encoder(n, m, k, a, b, ans);
task::encoder(n, m, k, a, b, ans);
}
void decoder(int n, int m, const char* a, char* ans) {
// if (m==70) task1::decoder(n, m, a, ans);
// else if (m==100) task2::decoder(n, m, a, ans);
// else if (m==1500) task5::decoder(n, m, a, ans);
// else if (m==300) task3::decoder(n, m, a, ans);
task::decoder(n, m, a, ans);
}