#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#ifdef LOCAL
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#else
#define dbg(...)
#endif
using namespace std;
vector<vector<int>> read_matrix() {
vector<vector<int>> m;
for (int i = 0; i < 10; ++i) {
m.emplace_back();
char line[11];
scanf("%s", line);
for (int j = 0; j < 10; ++j) {
m[i].emplace_back(line[j] - '0');
}
}
return m;
}
long long binomial[517][6];
void init_binom() {
for (int n = 0; n < 517; ++n) {
binomial[n][0] = 1;
for (int k = 1; k <= 5 && k <= n; ++k)
binomial[n][k] = binomial[n-1][k-1] + binomial[n-1][k];
}
}
// ==========================
// MULTISET CONVERSIONS
// ==========================
long long vector_to_number(const vector<int>& v) {
// Vector must be sorted and have size 5
dbg("Converting vector to a number: \n");
for (int i = 0; i < 5; ++i) {
dbg("%d ", v[i]);
}
dbg("\n");
long long result = binomial[v[0]+0][1] + binomial[v[1]+1][2] + binomial[v[2]+2][3] + binomial[v[3]+3][4] + binomial[v[4]+4][5];
dbg("Got result: %lld\n", result);
return result;
}
vector<int> number_to_vector(long long number) {
dbg("Converting number %lld to a vector", number);
vector<int> v(5);
for (int k = 5; k >= 1; --k) {
int n = k - 1;
while (n + 1 < 517 && binomial[n + 1][k] <= number)
++n;
v[k - 1] = n - (k - 1); // reverse the transform: subtract index
number -= binomial[n][k];
}
dbg("Got vector: \n");
for (int i = 0; i < 5; ++i) {
dbg("%d ", v[i]);
}
dbg("\n");
return v;
}
// ==========================
// BINARY CONVERSIONS
// ==========================
vector<int> number_to_binary(int number) {
// convert to binary, but first digit is least significant
// we need 9 binary digits
dbg("Converting number %d to binary", number);
vector<int> result;
for (int i = 0; i < 9; ++i) {
result.push_back(number % 2);
number /= 2;
}
dbg("Got binary: \n");
for (int i = 8; i >= 0; --i) {
dbg("%d", result[i]);
}
dbg("\n");
return result;
}
int binary_to_number(const vector<int>& binary) {
// convert to binary, but first digit is least significant
// we need 9 binary digits
dbg("Converting vector to number\n");
dbg("Got binary: \n");
for (int i = 8; i >= 0; --i) {
dbg("%d", binary[i]);
}
dbg("\n");
int result = 0;
int pow2 = 1;
for (int i = 0; i < 9; ++i) {
result += binary[i] * pow2;
pow2 *= 2;
}
dbg("Got result %d\n", result);
return result;
}
// powers of 2^38 that can be added by a tricky bit
const long long power_1_2_38 = 274877906944LL;
const long long power_2_2_38 = 549755813888LL;
const long long power_3_2_38 = 824633720832LL;
const long long power_4_2_38 = 1099511627776LL;
vector<vector<int>> encode(long long d) {
long long fit_2_38s = d / power_1_2_38;
long long mod_2_38s = d % power_1_2_38;
auto code_seq = number_to_vector(mod_2_38s);
vector<vector<int>> m;
m.push_back(vector{0,1,0,1,0,1,0,0,0,1}); // sum4-position row
m.push_back(vector{0,0,1,1,0,0,1,1,0,1}); // sum5-position row
m.push_back(vector{0,0,0,0,1,1,1,1,1,1}); // sum6-position row
m.push_back(vector{1,1,1,1,0,1,0,1,1,1}); // sum7-position row (must zero one bit to indicate fit_2_38s)
m[3][fit_2_38s] = 0;
m.push_back(vector{1,1,1,1,1,1,1,1,1,0}); // sum9-finder row (used to locate position-calibration-column)
for (auto num: code_seq) {
auto bin = number_to_binary(num);
vector<int> newvec;
for (int i = 0; i < 9; ++i) {
newvec.push_back(bin[i]);
}
newvec.push_back(0);
m.push_back(newvec);
}
dbg("FULL ENCODED MATRIX:\n");
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
dbg("%d ", m[i][j]);
}
dbg("\n");
}
dbg("\n");
return m;
}
int get_col_id_from_numidx(int numidx) {
// get real column number based on first 4 values
if (numidx == 0 || numidx == 8) return 0; // for first 4, 8bit can be either on or off
if (numidx == 1 || numidx == 9) return 1;
if (numidx == 2 || numidx == 10) return 2;
if (numidx == 3 || numidx == 11) return 3;
if (numidx == 4) return 4;
if (numidx == 13) return 5; // 8 bit always on
if (numidx == 6) return 6;
if (numidx == 14) return 7; // maybe weird but no time to change
if (numidx == 12) return 8;
dbg("WRONG COLUMN ID! %d\n", numidx);
return -1;
}
long long decode(const vector<vector<int>>& m) {
// m[i] = ith row of m
vector<int> row_1s;
int row9 = -1;
vector<int> real_row_idx{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
// m[real_row_idx[0]] - first colpos row
// m[real_row_idx[1]] - second colpos row
// m[real_row_idx[2]] - third colpos row
// m[real_row_idx[3]] - fourth colpos row
// m[real_row_idx[4]] - the 9row
vector<int> real_col_idx{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
// m[X][real_col_idx[9]] - Xth element of position calibration row
dbg("Searching for 9row...\n");
for (int i = 0; i < 10; ++i) {
int currow1s = 0;
for (int j = 0; j < 10; ++j) {
currow1s += m[i][j];
}
row_1s.push_back(currow1s);
if (currow1s == 9) {
dbg("Found 9row: %d\n", i);
row9 = i;
}
}
if (row9 == -1) {
dbg("Never found row9. Row1s:\n");
for (int i = 0; i < 10; ++i) {
dbg("%d ", row_1s[i]);
}
dbg("\n");
}
real_row_idx[4] = row9; // sum-9 finder row
for (int j = 0; j < 10; ++j) {
if (m[row9][j] == 0) {
// found position-calibration-column
real_col_idx[9] = j; // last column used for position calibration
}
}
dbg("Found position calibration column: %d\n", real_col_idx[9]);
for (int i = 0; i < 10; ++i) {
if (m[i][real_col_idx[9]] == 1) {
int rowpos = row_1s[i] - 4;
real_row_idx[rowpos] = i;
dbg("Found colpos row %d at position %d\n", rowpos, i);
}
}
// Now we are certain of first 5 rows and the last column.
// Let's get column IDs.
for (int j = 0; j < 10; ++j) {
if (j == real_col_idx[9]) continue; // skip position-calibration-column
int pow2 = 1;
int idx = 0;
for (int i = 0; i < 4; ++i) {
idx += pow2 * (m[real_row_idx[i]][j]);
pow2 *= 2;
}
int real_colid = get_col_id_from_numidx(idx);
dbg("Found column %d at position %d\n", real_colid, j);
real_col_idx[real_colid] = j;
}
long long fit_2_38s = 0LL;
if (m[real_row_idx[3]][real_col_idx[0]] == 0) {
fit_2_38s = 0LL;
}
if (m[real_row_idx[3]][real_col_idx[1]] == 0) {
fit_2_38s = 1LL;
}
if (m[real_row_idx[3]][real_col_idx[2]] == 0) {
fit_2_38s = 2LL;
}
if (m[real_row_idx[3]][real_col_idx[3]] == 0) {
fit_2_38s = 3LL;
}
dbg("We should add %lld 2^38s\n", fit_2_38s);
// Now process the proper data rows
vector<int> result_numbers;
dbg("RECONSTRUCTED ROW INDICES BEFORE GETTING NUMBERS:\n");
for (int i = 0; i < 10; ++i) {
dbg("%d ", real_row_idx[i]);
}
dbg("\n");
vector<int> unused_rows;
for (int ki = 0; ki < 10; ++ki) {
bool used = false;
for (int i = 0; i < 10; ++i) {
if (real_row_idx[i] == ki) used = true;
}
if (!used) unused_rows.push_back(ki);
}
int unused_row_num = 5;
for (auto urow: unused_rows) {
// data row
real_row_idx[unused_row_num] = urow;
unused_row_num++;
vector<int> binary;
for (int j = 0; j < 9; ++j) {
binary.push_back(m[urow][real_col_idx[j]]);
}
int number = binary_to_number(binary);
result_numbers.push_back(number);
}
dbg("RECONSTRUCTED INDICES:\n");
dbg("ROWS:\n");
for (int i = 0; i < 10; ++i) {
dbg("%d ", real_row_idx[i]);
}
dbg("\nCOLUMNS:\n");
for (int i = 0; i < 10; ++i) {
dbg("%d ", real_col_idx[i]);
}
dbg("\n");
dbg("RECONSTRUCTED MATRIX:\n");
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
dbg("%d ", m[real_row_idx[i]][real_col_idx[j]]);
}
dbg("\n");
}
dbg("\n");
ranges::sort(result_numbers);
long long res1 = vector_to_number(result_numbers);
long long res = res1 + fit_2_38s * power_1_2_38;
dbg("Read result: %lld\n", res);
return res;
}
void print_matrix(const vector<vector<int>>& m) {
for (unsigned long i = 0; i < m.size(); ++i) {
for (unsigned long j = 0; j < m[i].size(); ++j) {
printf("%d", m[i][j]);
}
printf("\n");
}
fflush(stdout);
}
int main() {
char s[10];
long long MAXN;
int t;
bool encode_mode = true;
init_binom();
// auto x = number_to_vector(123541322223LL);
// auto n = vector_to_number(x);
// auto n2 = vector_to_number(vector<int>{511,511,511,511,511});
// auto n3 = vector_to_number(vector<int>{0,0,0,1,0});
// auto n4 = vector_to_number(vector<int>{0,0,0,0,2});
// auto n5 = vector_to_number(vector<int>{0,0,1,1,1});
// auto n6 = vector_to_number(vector<int>{0,0,2,2,3});
scanf("%s", s);
if (strcmp(s, "Bajtek") == 0) {
// decode mode
encode_mode = false;
}
scanf("%lld %d", &MAXN, &t);
if (encode_mode) {
for (int i = 0; i < t; ++i) {
long long n;
scanf("%lld", &n);
auto m = encode(n);
print_matrix(m);
}
} else {
for (int i = 0; i < t; ++i) {
auto m = read_matrix();
dbg("Read input matrix\n");
for (int i = 0; i < 10; ++i) {
for (int j = 0 ; j < 10; ++j) {
dbg("%d", m[i][j]);
}
dbg("\n");
}
const long long d = decode(m);
printf("%lld\n", d);
fflush(stdout);
}
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #ifdef LOCAL #define dbg(...) fprintf(stderr, __VA_ARGS__) #else #define dbg(...) #endif using namespace std; vector<vector<int>> read_matrix() { vector<vector<int>> m; for (int i = 0; i < 10; ++i) { m.emplace_back(); char line[11]; scanf("%s", line); for (int j = 0; j < 10; ++j) { m[i].emplace_back(line[j] - '0'); } } return m; } long long binomial[517][6]; void init_binom() { for (int n = 0; n < 517; ++n) { binomial[n][0] = 1; for (int k = 1; k <= 5 && k <= n; ++k) binomial[n][k] = binomial[n-1][k-1] + binomial[n-1][k]; } } // ========================== // MULTISET CONVERSIONS // ========================== long long vector_to_number(const vector<int>& v) { // Vector must be sorted and have size 5 dbg("Converting vector to a number: \n"); for (int i = 0; i < 5; ++i) { dbg("%d ", v[i]); } dbg("\n"); long long result = binomial[v[0]+0][1] + binomial[v[1]+1][2] + binomial[v[2]+2][3] + binomial[v[3]+3][4] + binomial[v[4]+4][5]; dbg("Got result: %lld\n", result); return result; } vector<int> number_to_vector(long long number) { dbg("Converting number %lld to a vector", number); vector<int> v(5); for (int k = 5; k >= 1; --k) { int n = k - 1; while (n + 1 < 517 && binomial[n + 1][k] <= number) ++n; v[k - 1] = n - (k - 1); // reverse the transform: subtract index number -= binomial[n][k]; } dbg("Got vector: \n"); for (int i = 0; i < 5; ++i) { dbg("%d ", v[i]); } dbg("\n"); return v; } // ========================== // BINARY CONVERSIONS // ========================== vector<int> number_to_binary(int number) { // convert to binary, but first digit is least significant // we need 9 binary digits dbg("Converting number %d to binary", number); vector<int> result; for (int i = 0; i < 9; ++i) { result.push_back(number % 2); number /= 2; } dbg("Got binary: \n"); for (int i = 8; i >= 0; --i) { dbg("%d", result[i]); } dbg("\n"); return result; } int binary_to_number(const vector<int>& binary) { // convert to binary, but first digit is least significant // we need 9 binary digits dbg("Converting vector to number\n"); dbg("Got binary: \n"); for (int i = 8; i >= 0; --i) { dbg("%d", binary[i]); } dbg("\n"); int result = 0; int pow2 = 1; for (int i = 0; i < 9; ++i) { result += binary[i] * pow2; pow2 *= 2; } dbg("Got result %d\n", result); return result; } // powers of 2^38 that can be added by a tricky bit const long long power_1_2_38 = 274877906944LL; const long long power_2_2_38 = 549755813888LL; const long long power_3_2_38 = 824633720832LL; const long long power_4_2_38 = 1099511627776LL; vector<vector<int>> encode(long long d) { long long fit_2_38s = d / power_1_2_38; long long mod_2_38s = d % power_1_2_38; auto code_seq = number_to_vector(mod_2_38s); vector<vector<int>> m; m.push_back(vector{0,1,0,1,0,1,0,0,0,1}); // sum4-position row m.push_back(vector{0,0,1,1,0,0,1,1,0,1}); // sum5-position row m.push_back(vector{0,0,0,0,1,1,1,1,1,1}); // sum6-position row m.push_back(vector{1,1,1,1,0,1,0,1,1,1}); // sum7-position row (must zero one bit to indicate fit_2_38s) m[3][fit_2_38s] = 0; m.push_back(vector{1,1,1,1,1,1,1,1,1,0}); // sum9-finder row (used to locate position-calibration-column) for (auto num: code_seq) { auto bin = number_to_binary(num); vector<int> newvec; for (int i = 0; i < 9; ++i) { newvec.push_back(bin[i]); } newvec.push_back(0); m.push_back(newvec); } dbg("FULL ENCODED MATRIX:\n"); for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { dbg("%d ", m[i][j]); } dbg("\n"); } dbg("\n"); return m; } int get_col_id_from_numidx(int numidx) { // get real column number based on first 4 values if (numidx == 0 || numidx == 8) return 0; // for first 4, 8bit can be either on or off if (numidx == 1 || numidx == 9) return 1; if (numidx == 2 || numidx == 10) return 2; if (numidx == 3 || numidx == 11) return 3; if (numidx == 4) return 4; if (numidx == 13) return 5; // 8 bit always on if (numidx == 6) return 6; if (numidx == 14) return 7; // maybe weird but no time to change if (numidx == 12) return 8; dbg("WRONG COLUMN ID! %d\n", numidx); return -1; } long long decode(const vector<vector<int>>& m) { // m[i] = ith row of m vector<int> row_1s; int row9 = -1; vector<int> real_row_idx{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; // m[real_row_idx[0]] - first colpos row // m[real_row_idx[1]] - second colpos row // m[real_row_idx[2]] - third colpos row // m[real_row_idx[3]] - fourth colpos row // m[real_row_idx[4]] - the 9row vector<int> real_col_idx{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; // m[X][real_col_idx[9]] - Xth element of position calibration row dbg("Searching for 9row...\n"); for (int i = 0; i < 10; ++i) { int currow1s = 0; for (int j = 0; j < 10; ++j) { currow1s += m[i][j]; } row_1s.push_back(currow1s); if (currow1s == 9) { dbg("Found 9row: %d\n", i); row9 = i; } } if (row9 == -1) { dbg("Never found row9. Row1s:\n"); for (int i = 0; i < 10; ++i) { dbg("%d ", row_1s[i]); } dbg("\n"); } real_row_idx[4] = row9; // sum-9 finder row for (int j = 0; j < 10; ++j) { if (m[row9][j] == 0) { // found position-calibration-column real_col_idx[9] = j; // last column used for position calibration } } dbg("Found position calibration column: %d\n", real_col_idx[9]); for (int i = 0; i < 10; ++i) { if (m[i][real_col_idx[9]] == 1) { int rowpos = row_1s[i] - 4; real_row_idx[rowpos] = i; dbg("Found colpos row %d at position %d\n", rowpos, i); } } // Now we are certain of first 5 rows and the last column. // Let's get column IDs. for (int j = 0; j < 10; ++j) { if (j == real_col_idx[9]) continue; // skip position-calibration-column int pow2 = 1; int idx = 0; for (int i = 0; i < 4; ++i) { idx += pow2 * (m[real_row_idx[i]][j]); pow2 *= 2; } int real_colid = get_col_id_from_numidx(idx); dbg("Found column %d at position %d\n", real_colid, j); real_col_idx[real_colid] = j; } long long fit_2_38s = 0LL; if (m[real_row_idx[3]][real_col_idx[0]] == 0) { fit_2_38s = 0LL; } if (m[real_row_idx[3]][real_col_idx[1]] == 0) { fit_2_38s = 1LL; } if (m[real_row_idx[3]][real_col_idx[2]] == 0) { fit_2_38s = 2LL; } if (m[real_row_idx[3]][real_col_idx[3]] == 0) { fit_2_38s = 3LL; } dbg("We should add %lld 2^38s\n", fit_2_38s); // Now process the proper data rows vector<int> result_numbers; dbg("RECONSTRUCTED ROW INDICES BEFORE GETTING NUMBERS:\n"); for (int i = 0; i < 10; ++i) { dbg("%d ", real_row_idx[i]); } dbg("\n"); vector<int> unused_rows; for (int ki = 0; ki < 10; ++ki) { bool used = false; for (int i = 0; i < 10; ++i) { if (real_row_idx[i] == ki) used = true; } if (!used) unused_rows.push_back(ki); } int unused_row_num = 5; for (auto urow: unused_rows) { // data row real_row_idx[unused_row_num] = urow; unused_row_num++; vector<int> binary; for (int j = 0; j < 9; ++j) { binary.push_back(m[urow][real_col_idx[j]]); } int number = binary_to_number(binary); result_numbers.push_back(number); } dbg("RECONSTRUCTED INDICES:\n"); dbg("ROWS:\n"); for (int i = 0; i < 10; ++i) { dbg("%d ", real_row_idx[i]); } dbg("\nCOLUMNS:\n"); for (int i = 0; i < 10; ++i) { dbg("%d ", real_col_idx[i]); } dbg("\n"); dbg("RECONSTRUCTED MATRIX:\n"); for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { dbg("%d ", m[real_row_idx[i]][real_col_idx[j]]); } dbg("\n"); } dbg("\n"); ranges::sort(result_numbers); long long res1 = vector_to_number(result_numbers); long long res = res1 + fit_2_38s * power_1_2_38; dbg("Read result: %lld\n", res); return res; } void print_matrix(const vector<vector<int>>& m) { for (unsigned long i = 0; i < m.size(); ++i) { for (unsigned long j = 0; j < m[i].size(); ++j) { printf("%d", m[i][j]); } printf("\n"); } fflush(stdout); } int main() { char s[10]; long long MAXN; int t; bool encode_mode = true; init_binom(); // auto x = number_to_vector(123541322223LL); // auto n = vector_to_number(x); // auto n2 = vector_to_number(vector<int>{511,511,511,511,511}); // auto n3 = vector_to_number(vector<int>{0,0,0,1,0}); // auto n4 = vector_to_number(vector<int>{0,0,0,0,2}); // auto n5 = vector_to_number(vector<int>{0,0,1,1,1}); // auto n6 = vector_to_number(vector<int>{0,0,2,2,3}); scanf("%s", s); if (strcmp(s, "Bajtek") == 0) { // decode mode encode_mode = false; } scanf("%lld %d", &MAXN, &t); if (encode_mode) { for (int i = 0; i < t; ++i) { long long n; scanf("%lld", &n); auto m = encode(n); print_matrix(m); } } else { for (int i = 0; i < t; ++i) { auto m = read_matrix(); dbg("Read input matrix\n"); for (int i = 0; i < 10; ++i) { for (int j = 0 ; j < 10; ++j) { dbg("%d", m[i][j]); } dbg("\n"); } const long long d = decode(m); printf("%lld\n", d); fflush(stdout); } } return 0; } |
English