Niestety, nie byliśmy w stanie w pełni poprawnie wyświetlić tego pliku, ponieważ nie jest zakodowany w UTF-8.
Możesz pobrać ten plik i spróbować otworzyć go samodzielnie.
#include <cstdio> #include <string.h> #include <vector> #include <map> //#define DBG using namespace std; typedef unsigned long long ull; int n; ull c; ull cykl[19]; ull p10[19]; map<ull, ull> f18_cache; #ifdef DBG int f18_cache_hit = 0; #endif // DBG ///////////////////////////////////////////////////////////////////////////////////////////////////////////// void init () { int i; cykl[1] = 60; cykl[2] = 300; cykl[3] = 1500; for (i = 4; i <= 18; ++i) cykl[i] = cykl[i - 1] * 10; // it's magic :-) for (i = 1, p10[0] = 1; i <= 18; ++i) p10[i] = 10 * p10[i - 1]; f18_cache[0LL] = 0; f18_cache[1LL] = 1; } void czytaj() { int i; char dane[100]; scanf("%s", dane); n = strlen(dane); for (c = 0, i = 0; i < n; ++i) c = 10 * c + dane[i] - '0'; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// inline ull mul18(ull a, ull b) // mno�enie mod 10^18 { ull baza = p10[9]; ull a0 = a % baza; ull a1 = a / baza; ull b0 = b % baza; ull b1 = b / baza; return (a0 * b0 + baza * ((a0 * b1 + b0 * a1) % baza)) % p10[18]; } ull f18(ull k) // liczenie F(k) mod 10^18 wzorem Dijkstry { map<ull, ull>::iterator it = f18_cache.find(k); if(it != f18_cache.end()) { #ifdef DBG f18_cache_hit++; #endif // DBG return it->second; } ull n = (k + 1) / 2; ull f_1 = f18(n - 1); ull f = f18(n); ull res; if (k % 2) res = (mul18(f_1, f_1) + mul18(f, f)) % p10[18]; else res = mul18((2 * f_1 + f) % p10[18], f); f18_cache[k] = res; return res; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ull wynik() { /* Potrzeba pami�ta� list� k dla kt�rych F(k) ma sufiks o danej d�ugo�ci od 1 do d. Na pocz�tek trzeba j� zainicjowa� wyst�pieniami ostatniej cyfry, ale dla takich k, �e F(k) ma conajmniej d znak�w. To mo�na brute bo 18 cyfrowe b�d� od F(84). Po znalezieniu pierwszego wyst�pienia wiadomo, �e cykle id� max co 60 wi�c sprawdzamy tylko 59 kolejnych. Dla d=2..n przetwarzamy list� buduj�c kolejn�: bierzemy ka�de wyst�pienie kr�tszego sufiksu pocz�wszy od niego idziemy do przodu skokiem cykl[d - 1] ale nie dalej ni� cykl[d] od startu sprawdzamy czy dla F(k) ma zgodne d ostatnich cyfr - je�li tak to dodajemy do kolejnej listy */ int i; ull k = 1; // szukamy najmniejszego k, �e F(k) >= 10^(n - 1); np. najmniejsza z sufiksem d�ugo�ci 3 to 100 while (f18(k) < p10[n - 1]) k++; // teraz trzeba sprawdzi� kolejne cykl[1] liczb i wybra� te, kt�re maj� po��dan� ostatni� cyfr� sufiksu vector<ull> t; ull kmax = k + cykl[1] - 1; #ifdef DBG printf("sprawdzamy od %I64u do %I64u\n", k, kmax); #endif // DBG while (k <= kmax) { if (f18(k) % 10 == c % 10) t.push_back(k); k++; } for (int d = 2; t.size() && d <= n; ++d) { // analizujemy rosn�ce d�ugo�ci sufiks�w (o ile mamy jeszcze pasuj�ce liczby z poprzedniego d) #ifdef DBG printf("d=%d, t.size=%d, skok=%I64u, max=%I64u\n", d, t.size(), cykl[d - 1], cykl[d]); for(int q = 0; q < t.size(); ++q) printf(" %18I64u %18I64u\n", t[q], f18(t[q])); #endif // DBG vector<ull> nt; // tu b�d� znaleziony liczby pasuj�ce sufiksem d�ugo�ci d for (i = 0; i < t.size(); ++i) { k = t[i]; kmax = k + cykl[d] - 1; // b�dziemy analizowa� max cykl[d] liczb ze skokiem cykl[d - 1] while (k <= kmax) { if (f18(k) % p10[d] == c % p10[d]) { // pasuje na d ostatnich cyfrach if(d == n) return k; nt.push_back(k); } k += cykl[d - 1]; } } t = nt; // podmianka listy sufiks�w } return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// int main() { init(); czytaj(); if (n == 1) { // tablicujemy, aby kr�tko�� nie miesza�a przy liczeniu i wypisywaniu :-) static int wyn1[10] = {0, 1, 3, 4, -1, 5, -1, -1, 6, -1}; if (wyn1[c] >= 0) printf("%d\n", wyn1[c]); else printf("NIE\n"); return 0; } ull wyn = wynik(); #ifdef DBG printf("%d %d\n", f18_cache.size(), f18_cache_hit); #endif // DBG if (wyn) printf("%llu\n", wyn); 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 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 | #include <cstdio> #include <string.h> #include <vector> #include <map> //#define DBG using namespace std; typedef unsigned long long ull; int n; ull c; ull cykl[19]; ull p10[19]; map<ull, ull> f18_cache; #ifdef DBG int f18_cache_hit = 0; #endif // DBG ///////////////////////////////////////////////////////////////////////////////////////////////////////////// void init () { int i; cykl[1] = 60; cykl[2] = 300; cykl[3] = 1500; for (i = 4; i <= 18; ++i) cykl[i] = cykl[i - 1] * 10; // it's magic :-) for (i = 1, p10[0] = 1; i <= 18; ++i) p10[i] = 10 * p10[i - 1]; f18_cache[0LL] = 0; f18_cache[1LL] = 1; } void czytaj() { int i; char dane[100]; scanf("%s", dane); n = strlen(dane); for (c = 0, i = 0; i < n; ++i) c = 10 * c + dane[i] - '0'; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// inline ull mul18(ull a, ull b) // mno�enie mod 10^18 { ull baza = p10[9]; ull a0 = a % baza; ull a1 = a / baza; ull b0 = b % baza; ull b1 = b / baza; return (a0 * b0 + baza * ((a0 * b1 + b0 * a1) % baza)) % p10[18]; } ull f18(ull k) // liczenie F(k) mod 10^18 wzorem Dijkstry { map<ull, ull>::iterator it = f18_cache.find(k); if(it != f18_cache.end()) { #ifdef DBG f18_cache_hit++; #endif // DBG return it->second; } ull n = (k + 1) / 2; ull f_1 = f18(n - 1); ull f = f18(n); ull res; if (k % 2) res = (mul18(f_1, f_1) + mul18(f, f)) % p10[18]; else res = mul18((2 * f_1 + f) % p10[18], f); f18_cache[k] = res; return res; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ull wynik() { /* Potrzeba pami�ta� list� k dla kt�rych F(k) ma sufiks o danej d�ugo�ci od 1 do d. Na pocz�tek trzeba j� zainicjowa� wyst�pieniami ostatniej cyfry, ale dla takich k, �e F(k) ma conajmniej d znak�w. To mo�na brute bo 18 cyfrowe b�d� od F(84). Po znalezieniu pierwszego wyst�pienia wiadomo, �e cykle id� max co 60 wi�c sprawdzamy tylko 59 kolejnych. Dla d=2..n przetwarzamy list� buduj�c kolejn�: bierzemy ka�de wyst�pienie kr�tszego sufiksu pocz�wszy od niego idziemy do przodu skokiem cykl[d - 1] ale nie dalej ni� cykl[d] od startu sprawdzamy czy dla F(k) ma zgodne d ostatnich cyfr - je�li tak to dodajemy do kolejnej listy */ int i; ull k = 1; // szukamy najmniejszego k, �e F(k) >= 10^(n - 1); np. najmniejsza z sufiksem d�ugo�ci 3 to 100 while (f18(k) < p10[n - 1]) k++; // teraz trzeba sprawdzi� kolejne cykl[1] liczb i wybra� te, kt�re maj� po��dan� ostatni� cyfr� sufiksu vector<ull> t; ull kmax = k + cykl[1] - 1; #ifdef DBG printf("sprawdzamy od %I64u do %I64u\n", k, kmax); #endif // DBG while (k <= kmax) { if (f18(k) % 10 == c % 10) t.push_back(k); k++; } for (int d = 2; t.size() && d <= n; ++d) { // analizujemy rosn�ce d�ugo�ci sufiks�w (o ile mamy jeszcze pasuj�ce liczby z poprzedniego d) #ifdef DBG printf("d=%d, t.size=%d, skok=%I64u, max=%I64u\n", d, t.size(), cykl[d - 1], cykl[d]); for(int q = 0; q < t.size(); ++q) printf(" %18I64u %18I64u\n", t[q], f18(t[q])); #endif // DBG vector<ull> nt; // tu b�d� znaleziony liczby pasuj�ce sufiksem d�ugo�ci d for (i = 0; i < t.size(); ++i) { k = t[i]; kmax = k + cykl[d] - 1; // b�dziemy analizowa� max cykl[d] liczb ze skokiem cykl[d - 1] while (k <= kmax) { if (f18(k) % p10[d] == c % p10[d]) { // pasuje na d ostatnich cyfrach if(d == n) return k; nt.push_back(k); } k += cykl[d - 1]; } } t = nt; // podmianka listy sufiks�w } return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// int main() { init(); czytaj(); if (n == 1) { // tablicujemy, aby kr�tko�� nie miesza�a przy liczeniu i wypisywaniu :-) static int wyn1[10] = {0, 1, 3, 4, -1, 5, -1, -1, 6, -1}; if (wyn1[c] >= 0) printf("%d\n", wyn1[c]); else printf("NIE\n"); return 0; } ull wyn = wynik(); #ifdef DBG printf("%d %d\n", f18_cache.size(), f18_cache_hit); #endif // DBG if (wyn) printf("%llu\n", wyn); else printf("NIE\n"); return 0; } |