# パ研合宿2024 レク
## 競技概要
暗号化(Encode)と復号(Decode)を行う関数を作りましょう。暗号化のソースコードは他チームにも見られるので、なるべく読みにくくしましょう。他チームの暗号化のソースコードを読んで復号する関数を実装できたら得点が入ります。逆に、自分のチームの暗号化が破られたら得点を失います。
## ルール
この競技は全 3 ラウンドからなります。
各ラウンドは Defence パートと Attack パートからなります。以下のスケジュールで進行します。
| | Round 1 | Round 2 | Round 3 |
| ----------- | ------- | ------- | ------- |
| 9:20~9:50 |Defence | | |
| 9:50~10:20 |Attack |Defence | |
| 10:20~10:50 | |Attack |Defence |
| 10:50~11:20 | | |Attack |
## Defence パート
`Encode` 関数と `Decode` 関数を実装してください。その際、`Encode` 関数から `Decode` 関数を復元するのをなるべく難しくしてください。
例えば次のような方法が考えられます。
- 暗号化プログラムの難読化
- 暗号化アルゴリズムを複雑なものにする
なお、復号するプログラムは他チームに渡らないので難読化などをする必要はありません。
実行制限時間は 100 ケースの処理が 10 秒以内に収まるようにしてください。(そうじゃないと AtCoder のコードテストで動かないはず)
またコードの長さはコードテストで正常に実行できるようにしてください。
## Attack パート
他チームが実装した `Encode` 関数を見て `Decode` 関数を実装してください。
## 実装の詳細
あなたは $2$ つの関数を実装しなければならない。
$1$ つ目の関数は次の通りである。
```cpp
__int128_t Encode(__int128_t X)
```
- この関数は `namespace Encoder` 内で実装すること。
- 引数 $X$ は あなたが暗号化しなければならない整数 $X$ である。
- $X$ は $0 \leq X < 2^{32}$ を満たす整数である。
- 戻り値は $X$ を暗号化した整数 $Y$ である。
- 関数 `Encode` の戻り値 $Y$ は $0 \leq Y < 2^{64}$ を満たす必要がある。これが満たされない場合、**不正解 [1]** と判定される。
$2$ つ目の関数は次の通りである。
```cpp
__int128_t Decode(__int128_t Y)
```
- この関数は `namespace Decoder` 内で実装すること。
- 引数 $Y$ は `Encode` 関数が $X$ を暗号化した整数 $Y$ である。
- 関数 `Decode` の戻り値が $X$ と異なる場合,**不正解 [2]** と判定される。
## 重要な注意
- Google Spreadsheet がバグるので提出に文字 `"` を仕様してはならない。
- 内部での使用のために他の関数を実装したり、グローバル変数を宣言するのは自由である。ただし、すべてのグローバル変数と内部関数は `Encoder` または `Decoder` の名前空間内で宣言して、他のプログラムとの干渉を避ける必要がある。プログラム中のグローバル変数を共有することができるかもしれないが、自粛すること。
- あなたの提出したプログラムは、標準入力・標準出力,あるいは他のファイルといかなる方法でもやりとりしてはならない。ただし。標準エラー出力にデバッグ情報等を出力することは許される。
## やってはいけないこと
ズルしないでください。
## 採点の方法
$100$ ケースのテストケースを**ランダムに**生成する。すべてのテストケースで暗号化/復号が正しく行われた場合に正解と判定する。
## 提出の方法
スプシに `namespace` を提出。前で実演します、たぶん
## Tips
オーバーフローに注意してください。
できる難読化の例
- すごい大量の #define を使って混乱させる
- 大量にいらない変数を作る
- ビット演算などを用いて複雑な処理をする
- その他ルールに反しないかぎりなんでもあり。怪しかったら運営に DM で聞いてください。
## sample
```cpp=
#include <bits/stdc++.h>
using namespace std;
namespace Encoder {
__int128_t Encode(__int128_t X);
}
namespace Decoder {
__int128_t Decode(__int128_t Y);
}
namespace Judge {
void judge(){
const int T = 100;
random_device rd;
unsigned int seed = rd();
mt19937 mt(seed);
__int128_t xs[T],ys[T];
for(int i = 0;i < T;i++){
xs[i] = mt();
__int128_t Y = Encoder::Encode(xs[i]);
if(Y < 0 || Y >= ((__int128_t)1 << 64)){
string o = {87,114,111,110,103,32,65,110,115,119,101,114,32,91,49,93,32,40,89,32,115,104,111,117,108,100,32,98,101,32,48,32,60,61,32,89,32,60,32,50,94,54,52,41};
cout << o << endl;
return;
}
ys[i] = Y;
}
vector<int> perm(T);
iota(perm.begin(),perm.end(),0);
shuffle(perm.begin(),perm.end(),mt);
for(int i = 0;i < T;i++){
__int128_t X = Decoder::Decode(ys[perm[i]]);
if(X != xs[perm[i]]){
string o = {87,114,111,110,103,32,65,110,115,119,101,114,32,91,50,93,32,40,88,32,115,104,111,117,108,100,32,98,101,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,111,114,105,103,105,110,97,108,32,88,41},p = {88,32,61,32},q = {44,32,89,32,61,32},r = {44,32,68,101,99,111,100,101,40,89,41,32,61,32};
cout << o << endl;
cout << p << (long long)xs[perm[i]] << q << (long long)ys[perm[i]] << r << (long long)X << endl;
return;
}
}
string o = {65,99,99,101,112,116,101,100};
cout << o;
}
}
int main(){
Judge::judge();
}
namespace Encoder{
__int128_t Encode(__int128_t X){
return X + 1;
}
}
namespace Decoder{
__int128_t Decode(__int128_t Y){
return Y - 1;
}
}
```