#include #include #include #ifdef __PROGTEST__ #define debug(...) ((void)0) #else #define debug(fmt, ...) \ fprintf(stdout, "[DEBUG %s:%d %s()] " fmt "\n", __FILE__, __LINE__, \ __func__, ##__VA_ARGS__) #endif typedef long long int lli; typedef struct rails_t { lli rail_length_1; lli *larger_length; lli rail_length_2; lli *shorter_length; lli total_distance; } rails_t; // find the pivot using the smaller of the rail lengths // once pivot is found, the smallest step that will be used is // gcd(rail length 1, rail length 2) // int invalid_input() { printf("Nespravny vstup.\n"); return EXIT_FAILURE; } // https://www.geeksforgeeks.org/dsa/steins-algorithm-for-finding-gcd/ int gcd(int a, int b) { if (a == 0) return b; if (b == 0) return a; int k; for (k = 0; ((a | b) & 1) == 0; ++k) { a >>= 1; b >>= 1; } while ((a & 1) == 0) a >>= 1; do { while ((b & 1) == 0) b >>= 1; if (a > b) { a ^= b; b ^= a; a ^= b; } b = (b - a); } while (b != 0); return a << k; } lli find_pivot(rails_t rails) { lli pivot = -1; lli current_step; lli ratio = (rails.total_distance / *rails.shorter_length); for (lli i = 1; i < ratio; i++) { current_step = rails.total_distance - i * (*rails.shorter_length); if (current_step % (*rails.larger_length) == 0) { debug("Found pivot %lld\n", i); pivot = i; break; } } return pivot; } lli find_smallest_step(rails_t rails) { return *rails.larger_length / gcd(rails.rail_length_1, rails.rail_length_2); } lli find_solutions(rails_t rails, bool verbose) { lli variants = 0; lli pivot = find_pivot(rails); lli smallest_step = find_smallest_step(rails); debug("Smallest step = %lld", smallest_step); if (pivot != -1) { lli i; for (i = pivot;; i += smallest_step) { if ((rails.total_distance - i * (*rails.shorter_length)) < 0) { break; } if (verbose) { if (*rails.shorter_length == rails.rail_length_1) { printf("= %lld * %lld + %lld * %lld\n", rails.rail_length_1, i, rails.rail_length_2, (rails.total_distance - i * rails.rail_length_1) / rails.rail_length_2); } else { printf("= %lld * %lld + %lld * %lld\n", rails.rail_length_1, (rails.total_distance - i * rails.rail_length_2) / rails.rail_length_1, rails.rail_length_2, i); } } variants++; } } return variants; } int main() { printf("Delky koleji:\n"); lli rail_length_1 = -1, rail_length_2 = -1; if (scanf(" %lld %lld", &rail_length_1, &rail_length_2) != 2 || (rail_length_1 <= 0 && rail_length_2 <= 0) || (rail_length_1 == rail_length_2)) { return invalid_input(); } printf("Vzdalenost:\n"); lli total_distance = 0; char operand; if (scanf(" %c %lld", &operand, &total_distance) != 2 || (operand != '+' && operand != '-')) { return invalid_input(); } lli variants = 0; bool verbose = operand == '+'; if (total_distance < 0) { return invalid_input(); } if (total_distance == 0) { if (verbose) { printf("= %lld * 0 + %lld * 0\n", rail_length_1, rail_length_2); } variants++; } else if (rail_length_1 == 0 && total_distance % rail_length_2 == 0) { if (verbose) { printf("= %lld * %lld + %lld * 0\n", rail_length_1, total_distance / rail_length_2, rail_length_2); } } else if (rail_length_2 == 0 && total_distance % rail_length_1 == 0) { if (verbose) { printf("= %lld * 0 + %lld * %lld\n", rail_length_1, rail_length_2, total_distance / rail_length_1); } } else if (rail_length_1 > 0 && rail_length_2 > 0) { lli *smaller = rail_length_1 > rail_length_2 ? &rail_length_2 : &rail_length_1; lli *larger = rail_length_1 > rail_length_2 ? &rail_length_1 : &rail_length_2; rails_t rails; rails.rail_length_1 = rail_length_1; rails.rail_length_2 = rail_length_2; rails.total_distance = total_distance; rails.shorter_length = smaller; rails.larger_length = larger; if (total_distance % rail_length_1 == 0) { if (verbose) { printf("= %lld * %lld + %lld * 0\n", rail_length_1, total_distance / rail_length_1, rail_length_2); } variants++; } variants += find_solutions(rails, verbose); } if (variants != 0) { printf("Celkem variant: %lld\n", variants); } else { printf("Reseni neexistuje.\n"); } }