#include #include // struktura, reprezentující sloupec, do kterého se umíme dostat struct Solution { // první řádek, na který se umíme dostat int Level; // číslo balíčku, který jsme použili na přístup do aktuálního sloupce int LastBundle; }; // N ze zadání int N; // počet použitých druhů balíčků // (druhá polovina balíčků obsahuje jen balíčky s hmotností, která už v první polovině je) int bundlesLength; // pole předpočítaných velikostí balíčků int* bundles; // pole řešení pro sloupce struct Solution* solutions; // číslo aktuálního průchodu, tedy čísla řádku int currentLevel; // funkce, která označí sloupce dostupného ze zadaného void newSolutions(int pos) { for (int i = 1; i < bundlesLength; i++) { int newPos = (pos + bundles[i]) % N; int newLevel = currentLevel + (pos + bundles[i]) / N; if (newPos != 0 && (solutions[newPos].Level == 0 || solutions[newPos].Level > newLevel)) { solutions[newPos].Level = newLevel; solutions[newPos].LastBundle = i; } } } int main(void) { // H ze zadání int H; FILE* input = fopen("balicky.in", "r"); fscanf(input, "%d %d", &N, &H); int evenN = N % 2 == 0; bundlesLength = (N + 1) / 2; bundles = (int*)malloc(sizeof(int) * bundlesLength); // předpočítání velikostí balíčků for (int i = 0; i < bundlesLength; i++) { bundles[i] = (N - i) * (i + 1); if (evenN) bundles[i] /= 2; } // pokud je N sudé, sloupce s lichým číslem nejsou dostupné a můžeme je tedy zcela ignorovat, // což uděláme tak, že N i H snížíme na polovinu if (evenN) { H = (H + 1) / 2; N /= 2; } // číslo řádku cílového políčka int quotient = H / N; // číslo sloupce cílového políčka int remainder = H % N; solutions = (struct Solution*)calloc(N, sizeof(struct Solution)); currentLevel = 0; solutions[0].LastBundle = 0; solutions[0].Level = 1; newSolutions(0); int done = 0; int currentPosition; // průchod seznamem sloupců while (!done) { currentLevel++; for (currentPosition = 0; currentPosition < N; currentPosition++) { if (solutions[currentPosition].Level > 0 && solutions[currentPosition].Level <= currentLevel) { if ((currentPosition == remainder && solutions[currentPosition].Level <= quotient) || (currentLevel > quotient) || (currentLevel == quotient && currentPosition >= remainder)) { done = 1; break; } } if (solutions[currentPosition].Level == currentLevel) newSolutions(currentPosition); } } int* counts = (int*)calloc(bundlesLength, sizeof(int)); // započítání balíčků velikosti N if (quotient > currentLevel) counts[0] = quotient - currentLevel; // započítání ostatních balíčků zpětným průchodem int current = currentPosition + currentLevel * N; while (current > 0) { struct Solution solution = solutions[current % N]; int bundle = solution.LastBundle; counts[bundle] += 1; current -= bundles[bundle]; } FILE* output = fopen("balicky.out", "w"); for (int i = 0; i < bundlesLength; i++) if (counts[i] != 0) fprintf(output, "%d %d\n", counts[i], i + 1); return 0; }