赌场 题解
可是啊 我却 却愿意去相信
最渺小最微弱最柔软最无畏的你
赌场 题解
下文记 Azzurro 为小 A,Bordeaux 为小 B,Chiaro 为小 C。
理论信息位
小 A/B 获胜的关键是通过二维矩阵使得小 B 能够准确地接受小 A 传递来的信息。
考虑到
由于小 C 可以对一条路径进行修改,而这条路径的长度恒定为
但是你注意到:
维护信息位
一个直接的思路是维护
如果我们考虑以一行或者一列为一个单位维护,这样的信息位数确实很多,但是小 C 可能在一行走很多步,这样就 WA 了。所以我们必须换一种方式维护信息。
我们考虑:非信息位的个数为
信息加密
假设我们现在是小 B。在这个单元内,我们想知道小 A 给我们的原始信息是什么。
显然小 C 对原始信息的一位做了操作。我们需要排除这一位的影响。
假设我们知道上一单元,小 C 走到了
所以我们对于一个对角线,维护
这样,当小 B 拿到矩阵之后,判断异或位的信息是否和所有
-
信息对得上时:
-
-
信息对不上时:
-
对角线分类讨论
显然斜对角线有两种:
红色系的对角线
蓝色系对角线
对这两种对角线,我们选择的信息位是不一样的。
一个显然的思路是:
这样的紫色位置选的是对的,但是如果绿色也这么选,只能得
为什么呢?
我们考虑当小 C 恰好走到异或位的情况。如果这个异或位的
如果小 C 现在在
如果小 C 下移,那么就会出现信息差异,从而错误。
如果小 C 右移,那么还是会出现信息差异。
这样会导致我们无法区分这两种情况,从而爆炸。
所以我们必须把异或位选在一个
这样就完成了。然后就是一堆细节,比如 0-index 和 1-index 啥的,还有通信题难以调试的问题。
::::success[Code] 初版代码太丑了,经过了 Deepseek 格式化,所以会和我平时的代码有些不一样。
#include<bits/stdc++.h>
using namespace std;
std::vector<std::vector<int>> Azzurro(int n, int L, std::string S){
std::string s = ' ' + S; n = 8;
int l = L;
while(l <= 51){ s += 'A'; l++; }
std::vector<std::vector<int>> a;
a.resize(9);
for(int i=0;i<=8;i++)a[i].resize(9);
a[1][1] = (s[1] == 'A' ? 0 : 1);
int tot = 1;
for(int i=3;i<=15;i++){
if(i <= 8+1){
int x=i-1, y=1, sum=0;
for(;x>=1;x--,y++){
if(x==1) a[x][y]=sum;
else {
a[x][y] = (s[++tot]=='A' ? 0 : 1);
if(x&1) sum ^= a[x][y];
}
}
} else {
int x=i-8, y=8, sum=0;
for(;x<=n;y--,x++){
if(x==7) a[x][y]=sum;
else {
a[x][y] = (s[++tot]=='A' ? 0 : 1);
if(x&1) sum ^= a[x][y];
}
}
}
}
a[8][8] = (s[51]=='A' ? 0 : 1);
std::vector<std::vector<int>> b;
b.resize(8);
for(int i=0;i<=7;i++)b[i].resize(8);
for(int i=1;i<=8;i++)
for(int j=1;j<=8;j++)
b[i-1][j-1] = a[i][j];
return b;
}
char getc(int x){
return x==0 ? 'A' : 'B';
}
std::string Bordeaux(int n, int l, std::vector<std::vector<int>> b){
std::string s = " ", ans = ""; n = 8;
std::vector<std::vector<int>> a;
a.resize(9);
for(int i=0;i<=8;i++)a[i].resize(9);
for(int i=1;i<=8;i++)
for(int j=1;j<=8;j++)
a[i][j] = b[i-1][j-1];
a[1][1] ^= 1;
int X=1, Y=1;
for(int i=3;i<=15;i++){
if(i <= n+1){
int x=i-1, y=1;
int sum = a[y][x];
for(;x>=1;x--,y++){
if(x==1){
if(sum==0){ if(X&1) X++; else Y++; }
else { if(X&1) Y++; else X++; }
a[X][Y] ^= 1;
} else {
if(x&1) sum ^= a[x][y];
}
}
} else {
int x=i-8, y=8;
int sum = a[7][i-7];
for(;x<=n;y--,x++){
if(x>=n-1){
continue;
} else {
if(x&1) sum ^= a[x][y];
}
}
if(X==8) Y++;
else if(Y==8) X++;
else if(sum==0){ if(X&1) X++; else Y++; }
else { if(X&1) Y++; else X++; }
a[X][Y] ^= 1;
}
}
a[8][8] ^= 1;
for(int k=2;k<=16;k++){
if(k<=9){
for(int j=1,i;j<k;j++){
i=k-j;
if(i==1){ if(j==1) s+=getc(a[i][j]); continue; }
if(j==8){ if(i==8) s+=getc(a[i][j]); continue; }
s += getc(a[i][j]);
}
} else {
for(int i=k-8, j=8; i<=8; i++, j--){
if(i==7 && j==k-7) continue;
s += getc(a[i][j]);
}
}
}
for(int i=1;i<=l;i++) ans += s[i];
return ans;
}
::::