#include<cstdio> #include<cstring> #include<string> #include<vector> #define FOR(i, a, b) for (int i = (a); i < (b); ++i) #define REP(i, n) FOR(i, 0, n) using namespace std; typedef unsigned long long ull; ull multiplicate(ull a, ull b, ull modulo); struct matrix { ull m[2][2]; matrix(ull b1, ull b2, ull b3, ull b4) { m[0][0] = b1; m[0][1] = b2; m[1][0] = b3; m[1][1] = b4; } matrix mult(matrix const& A, const ull modulo) const { ull b[2][2] = {{0, 0}, {0, 0}}; for(int i=0; i < 2; ++i) for(int j=0; j < 2; ++j) for(int k=0; k < 2; ++k) { b[i][j] = ((b[i][j] + multiplicate(m[i][k], A.m[k][j], modulo)) % modulo); } return matrix(b[0][0], b[0][1], b[1][0], b[1][1]); } }; ull multiplicate(ull a, ull b, ull modulo) { if (a == 0 || b == 0 || ((64 - __builtin_clzll(a)) + (64 - __builtin_clzll(b))) <= 64) { return (a*b) % modulo; } ull result = 0; while (b) { if(b&1) { result = ((result + a) % modulo); } b /= 2; a = ((a + a) % modulo); } return result; } unsigned long long mods[19]; void fill_mods() { mods[0] = 1; mods[1] = 60; mods[2] = 300; mods[3] = 1500; FOR(i, 4, 19) { mods[i] = mods[i - 1] * 10; } } matrix power(matrix const& A, unsigned long long k, ull modulo) { matrix result(1, 0, 0, 1); matrix powe = A; while (k != 0) { if (k&1) { result = result.mult(powe, modulo); } k /= 2; powe = powe.mult(powe, modulo); } return result; } unsigned long long mod_fib(unsigned long long k, unsigned long long modulo) { matrix A(0, 1, 1, 1); matrix B = power(A, k, modulo); return B.m[0][1]; } ull get_ull(char * raw_ull) { return std::stoull (string(raw_ull)); } char c[19]; int len; vector<unsigned long long> remiders; int main() { fill_mods(); scanf("%s", c); len = strlen(c); remiders.push_back(0); int lvl = 0; unsigned long long ten = 1; while (lvl != len) { unsigned long long target = get_ull(c + (len - 1 - lvl)); vector<unsigned long long> new_remiders; ten *= 10; for (unsigned long long remider : remiders) { for (unsigned long long scale = 0; scale < (mods[lvl + 1] / mods[lvl]); ++scale) { unsigned long long possible_remider = remider + mods[lvl] * scale; if (mod_fib(possible_remider, ten) == target) { new_remiders.push_back(possible_remider); } } } lvl++; remiders.swap(new_remiders); } if (remiders.size()) { printf("%llu\n", remiders[0]); } else { printf("NIE\n"); } 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 | #include<cstdio> #include<cstring> #include<string> #include<vector> #define FOR(i, a, b) for (int i = (a); i < (b); ++i) #define REP(i, n) FOR(i, 0, n) using namespace std; typedef unsigned long long ull; ull multiplicate(ull a, ull b, ull modulo); struct matrix { ull m[2][2]; matrix(ull b1, ull b2, ull b3, ull b4) { m[0][0] = b1; m[0][1] = b2; m[1][0] = b3; m[1][1] = b4; } matrix mult(matrix const& A, const ull modulo) const { ull b[2][2] = {{0, 0}, {0, 0}}; for(int i=0; i < 2; ++i) for(int j=0; j < 2; ++j) for(int k=0; k < 2; ++k) { b[i][j] = ((b[i][j] + multiplicate(m[i][k], A.m[k][j], modulo)) % modulo); } return matrix(b[0][0], b[0][1], b[1][0], b[1][1]); } }; ull multiplicate(ull a, ull b, ull modulo) { if (a == 0 || b == 0 || ((64 - __builtin_clzll(a)) + (64 - __builtin_clzll(b))) <= 64) { return (a*b) % modulo; } ull result = 0; while (b) { if(b&1) { result = ((result + a) % modulo); } b /= 2; a = ((a + a) % modulo); } return result; } unsigned long long mods[19]; void fill_mods() { mods[0] = 1; mods[1] = 60; mods[2] = 300; mods[3] = 1500; FOR(i, 4, 19) { mods[i] = mods[i - 1] * 10; } } matrix power(matrix const& A, unsigned long long k, ull modulo) { matrix result(1, 0, 0, 1); matrix powe = A; while (k != 0) { if (k&1) { result = result.mult(powe, modulo); } k /= 2; powe = powe.mult(powe, modulo); } return result; } unsigned long long mod_fib(unsigned long long k, unsigned long long modulo) { matrix A(0, 1, 1, 1); matrix B = power(A, k, modulo); return B.m[0][1]; } ull get_ull(char * raw_ull) { return std::stoull (string(raw_ull)); } char c[19]; int len; vector<unsigned long long> remiders; int main() { fill_mods(); scanf("%s", c); len = strlen(c); remiders.push_back(0); int lvl = 0; unsigned long long ten = 1; while (lvl != len) { unsigned long long target = get_ull(c + (len - 1 - lvl)); vector<unsigned long long> new_remiders; ten *= 10; for (unsigned long long remider : remiders) { for (unsigned long long scale = 0; scale < (mods[lvl + 1] / mods[lvl]); ++scale) { unsigned long long possible_remider = remider + mods[lvl] * scale; if (mod_fib(possible_remider, ten) == target) { new_remiders.push_back(possible_remider); } } } lvl++; remiders.swap(new_remiders); } if (remiders.size()) { printf("%llu\n", remiders[0]); } else { printf("NIE\n"); } return 0; } |