1. 程式人生 > 其它 >UOJ728 【JOISC2022】壞掉的裝置 2 【通訊,構造】

UOJ728 【JOISC2022】壞掉的裝置 2 【通訊,構造】

題目連結

對於這種損失資訊的通訊題,關鍵是在於找不變數那找不到怎麼辦 /ll

\(\{t_i\}=\texttt{1010}\cdots\),將 \(\texttt{01}\) 分別看做 \(-1\)\(+1\),則歸併後對 \(\{s_i\}\) 的字首和影響不大。

此時問題轉化為選擇 \(10^{18}\) 個長度 \(\le 140\)\(\texttt{01}\)\(\{s_i\}\) 使得可以由 \(\text{merge}(s,t)\) 還原出 \(\{s_i\}\)

具體來說,\(\{t_i\}\) 的影響是時不時會 \(\pm 1\),但字首和 \(\in\{0,1\}\)

,所以構造如下:每個極長相同連續段長度都是 \(\ge 3\) 的奇數,除了第一段如果是連續 \(\texttt{1}\) 那麼長度為偶數;對應的解碼方法是字首和到 \(+2\) 時記一個 \(\texttt 1\) 並歸零,到 \(-2\) 時記一個 \(\texttt 0\) 並歸零,然後把每個連續段長度 \(x\) 擴大到 \(2x+1\)(同樣特判第一段)

這時候所需長度已經比較接近了,需要再優化細節卡卡常:

  • 末尾加一堆交替的 \(\texttt{0}\)\(\texttt{1}\)
  • 開頭加一個 \(\texttt{1}\),然後反轉所有 \(\texttt{01}\)
#include"Anna.h"
#include<bits/stdc++.h>
typedef long long LL;
typedef std::vector<int> VI;
namespace {
const int N = 150;
LL f[N];
}
int Declare(){
	f[1] = f[2] = 1;
	for(int i = 3;i < N;++ i)
		f[i] = f[i-2] + f[i-3] + 1;
	return 140;
}
std::pair<VI, VI> Anna(LL k){
	-- k; int flg = k & 1; k >>= 1;
	int len = 1; while(k >= f[len]) k -= f[len++];
	VI s, t(len); s.reserve(len);
	int fl = flg; s.push_back(fl);
	for(int i = len;k;){
		if(k <= f[i-2]){-- k; i -= 2;}
		else {s.push_back(fl ^= 1); k -= f[i-2] + 1; i -= 3;}
		s.push_back(fl); s.push_back(fl);
	}
	while(s.size() < len) s.push_back(fl ^= 1);
	for(int i = 0;i < len;++ i) t[i] = flg ^ (i & 1);
	return std::make_pair(s, t);
}
#include"Bruno.h"
#include<bits/stdc++.h>
typedef long long LL;
typedef std::vector<int> VI;
namespace {
const int N = 150;
LL f[N];
}
LL Bruno(VI u){
	if(!f[1]){
		f[1] = f[2] = 1;
		for(int i = 3;i < N;++ i)
			f[i] = f[i-2] + f[i-3] + 1;
	}
	LL ans = 0; int len = u.size() >> 1;
	for(int i = 1;i < len;++ i) ans += f[i];
	int flg = u[0], fl = flg, sum = 0;
	for(int i = 1, j = len;i < u.size();++ i){
		sum += 2 * u[i] - 1;
		if(abs(sum) == 2){
			if((sum == 2) == fl){++ ans; j -= 2;}
			else {ans += f[j-2] + 1; j -= 3;}
			fl = sum == 2; sum = 0;
		}
	}
	return ans * 2 + flg + 1;
}