|
#include <stdio.h> |
|
#include <stdint.h> |
|
#include <inttypes.h> |
|
#include <string> |
|
#include <vector> |
|
#include <iostream> |
|
#include <sstream> |
|
#include <algorithm> |
|
#include <iterator> |
|
#include <array> |
|
|
|
using namespace std; |
|
|
|
typedef uint32_t u32; |
|
typedef uint64_t u64; |
|
const u64 M = UINT64_C(1) << 32; |
|
const u64 A = UINT64_C(0x5D588B656C078965); |
|
const u64 B = UINT64_C(0x269EC3); |
|
const u64 A23 = UINT64_C(0x49cf1bd3cc99868d); // (A,B)を23回合成したもの |
|
const u64 B23 = UINT64_C(0x2e18c7366cb1d351); |
|
const u64 Ainv = UINT64_C(0xdedcedae9638806d); |
|
const u64 Binv = UINT64_C(0x9b1ae6e9a384e6f9); |
|
|
|
const std::vector<string> NAME = {"ハジメ", "ツギコ", "イチミ", "ミライ", "チユ", "パソキチ", "アートス", "アリョーナ", "アッツォ", "アントニナ", "アルヒッパ", "アリビーナ", "アントン", "アスタ", "アンセルミ", "アンネリ", "アルピ", "アネルマ", "アッラン", "アイニッキ", "アーポ", "アーム", "アクセル", "アッスンタ", "アッサール", "アラベッラ", "アティリオ", "アンネッタ", "アマンド", "アガタ", "ジャコブ", "ジャサント", "ジェローム", "ジョゼ", "ジュスタン", "ジャンヌ", "ジュール", "ジュリー", "ジャスパー", "ジェーン", "ジェヒュー", "ジャニス", "ジョナス", "ジェナ", "ジャレッド", "ジョアン", "ジャン", "ジョイス", "ジョエル", "ジョスリン", "ジョシュア", "ジェシー", "ジェリー", "ジュディス", "チェレン", "ホミカ", "アーティ", "カミツレ", "ヤーコン", "フウロ", "シャガ", "シズイ"}; |
|
|
|
const int MAX_DAYS = 10; |
|
int openedShops[8]; |
|
int emerged[MAX_DAYS][12]; |
|
int numDays; |
|
int numFans; |
|
|
|
u64 nxt(u64 s) { |
|
return A * s + B; |
|
} |
|
int rnd(u64 s, int n) { |
|
return ((s >> 32) * n) >> 32; |
|
} |
|
u32 update(u32 s) { |
|
return (s * UINT64_C(0x5d583d6d6c078979) + 0x26a693) >> 32; |
|
} |
|
|
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) |
|
|
|
bool exist(const int *array, int len, int value) { |
|
for (int i = 0; i < len; i++) { |
|
if (array[i] == value) return true; |
|
} |
|
return false; |
|
} |
|
|
|
bool okOneDay(u32 seed, const int *em) { |
|
int fans[12]; |
|
u64 s = seed; |
|
int count = 0; |
|
s = s * A23 + B23; |
|
while (true) { |
|
int fan = rnd(s, 48) + 6; |
|
s = nxt(s); |
|
if (!exist(openedShops, ARRAY_SIZE(openedShops), fan) && !exist(fans, count, fan)) { |
|
fans[count++] = fan; |
|
if (!exist(em, numFans, fan)) return false; |
|
if (count == numFans) break; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
bool okSeed(u32 s) { |
|
for (int i = 0; i < numDays; i ++) { |
|
if(!okOneDay(s, emerged[i])) return false; |
|
s = update(s); |
|
} |
|
return true; |
|
} |
|
|
|
|
|
vector<string> split(const string &str, char delim){ |
|
istringstream iss(str); string tmp; vector<string> res; |
|
while(getline(iss, tmp, delim)) res.push_back(tmp); |
|
return res; |
|
} |
|
|
|
int input_fan_names(int *dest, int max) { |
|
string str; |
|
getline(cin, str); |
|
vector<string> names = split(str, ' '); |
|
vector<int> ret; |
|
int i = 0; |
|
for (const string name : names) { |
|
if (i >= max) { |
|
cerr << "入力が" << max << "件を超えました"; |
|
throw 1; |
|
} |
|
auto it = find(NAME.begin(), NAME.end(), name); |
|
if (it == NAME.end()) { |
|
cerr << name << "という名前はありません" << endl; |
|
throw 1; |
|
} else { |
|
dest[i++] = it - NAME.begin(); |
|
} |
|
} |
|
return i; |
|
} |
|
|
|
int main() { |
|
string str; |
|
cout << "お店を開いているファンの名前を入力 (スペース区切り)" << endl; |
|
cout << ">"; |
|
input_fan_names(openedShops, 8); |
|
numFans = -1; |
|
cout << "以下で出現したファンの名前を入力します。終わるときは空行を入力。" << endl; |
|
for (numDays = 0; numDays < MAX_DAYS; numDays ++) { |
|
cout << (numDays+1) << "日目のファン >"; |
|
int num = input_fan_names(emerged[numDays], 12); |
|
if (num == 0) break; |
|
if (numFans == -1) numFans = num; |
|
if (num != numFans) { |
|
cerr << "ファンの数は一定にしてください" << endl; |
|
return 1; |
|
} |
|
} |
|
|
|
for (u32 seed = 1; seed != 0; seed++) { |
|
if ((seed & 0xfffff) == 0) printf("%.8x\r", seed); |
|
if (okSeed(seed)) { |
|
printf("found %.8x\n", seed); |
|
} |
|
} |
|
printf("finish\n"); |
|
getchar(); |
|
return 0; |
|
} |