题解 密码

传送门

很有趣的一道交互题

首先通过加入一些特征码来标记有用信息可以拿到 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);
}
posted @ 2022-02-19 19:21  Administrator-09  阅读(2)  评论(0编辑  收藏  举报