// Ultraviolet A Problem 113-power of cryptography // verdict: accepted // submission date: 2011-11-25 // ultraviolet A Run Time: 0.312 S // All Rights Reserved (c) 2011, Qiu. Metaphysis # Yeah dot net // [solution] // This question can be classified as a high-precision arithmetic question. //// A simple large number operation. Use the template code. Use the binary method to search for K values. Is it better to use Java? I have high precision // arithmetic support. However, I prefer C ++. //// After the AC is compared with other people's code, I found that there are more clever methods I did not think. Although the Code is a bit untrustworthy at first, it is OK after analysis. //// The following is the AC code used by others. Why is it feasible? From the first point of view, it seems that POW is not a precise calculation, but a // approximate value. Why does it get the correct answer? It is because the base number is an integer, because the difference between any two integers is at least 1, // plus the power relationship, as long as the two numbers are not equal, the difference in the power value can be reflected in the precision of the double value. Why? Because the // question is limited to 1 <= k <= 10 ^ 9, there are: // (k + 1) ^ n-k ^ n> N * k ^ (n-1) // while N * k ^ (n-1)/K ^ n = N/K, because 1 <= k <= 10 ^ 9, as long as the difference between two numbers is 1, the difference between the N idempotence // can be reflected by the precision of the double number, because the double number has a precision of 15 bits, for any n value, in the range of question/given 1 <= k <= 10 ^ 9, as long as the base number is not equal, its power must not be equal after being expressed by double. Therefore, you can use the // POW + binary method to determine which integer the base number is. However, when K increases, this method will definitely fail. it is foreseeable that when K's number of digits // exceeds the number of double's precision digits, this method will not be able to find the correct base number. However, using a large number operation is still feasible. //// # Include <stdio. h> // # include <math. h> // # include <float. h> /// int main () // {// double N, P; // while (scanf ("% lf", & N, & P )! = EOF) // {// int begin = 1; // int end = 1000000000; // int mid; /// // binary search. // While (begin <= END) // {// mid = (begin + end)/2; // double temp = POW (MID, N ); // If (temp = P) // {// printf ("% d \ n", mid); // break; /// else if (temp> P) // end = mid-1; // else // begin = Mid + 1; ///} // return 0; //} # include <iostream> # include <vector> # include <iomanip> # include <cstdlib> using namespace STD; class INTEGER {friend ostream & operator <(ostream &, const integer &); Public: integ Er () {}; // converts an integer to a large integer. INTEGER (long a) {if (a = 0) digits. push_back (0); else {While (a) {digits. push_back (a % base); A/= base ;}}; // convert the string to a large integer. The format is not checked. The default format is correct. INTEGER (string line) {While (line. length ()> = width) {digits. push_back (atoi (line. substr (line. length ()-width ). data (); line = line. substr (0, line. length ()-width);} If (line. length () digits. push_back (atoi (line. data ()));};~ INTEGER () {}; integer operator * (const integer &); integer & operator * = (const integer &); bool operator <(integer &); bool operator = (integer &); Private: void zero_justify (void); vector <unsigned int> digits; // digits. Static unsigned int const base = 10000; // base number. Static unsigned int const width = 4; // digital width .}; // Reload the output symbol <. Ostream & operator <(ostream & OS, const integer & number) {OS <number. digits [number. digits. size ()-1]; for (INT I = number. digits. size ()-2; I> = 0; I --) OS <SETW (number. width) <setfill ('0') <number. digits [I]; return OS;} // remove the leading 0 produced by the large number operation. Void INTEGER: zero_justify (void) {for (INT I = digits. size ()-1; I> = 1; I --) {If (digits [I] = 0) digits. erase (digits. begin () + I); elsebreak;} integer & INTEGER: Operator * = (const integer & B) {return * This = * This * B;} // multiplication. Integer INTEGER: Operator * (const integer & B) {INTEGER C; // pre-allocate sufficient space. C. digits. resize (digits. size () + B. digits. size (); fill (C. digits. begin (), C. digits. end (), 0); // calculates the number of rows and adds them one by one. For (INT I = 0; I <B. digits. size (); I ++) for (Int J = 0; j <digits. size (); j ++) {C. digits [I + J] + = digits [J] * B. digits [I]; C. digits [I + J + 1] + = C. digits [I + J]/base; C. digits [I + J] % = base;} // remove the leading 0. C. zero_justify (); Return C;} // The overload is less than the symbol. Bool INTEGER: Operator <(integer & B) {If (digits. size () <B. digits. size () return true; If (digits. size ()> B. digits. size () return false; For (INT I = digits. size ()-1; I> = 0; I --) if (digits [I]! = B. digits [I]) return digits [I] <B. digits [I]; return false;} // reload equals to the symbol. Bool INTEGER: Operator = (integer & B) {If (digits. Size ()! = B. digits. Size () return false; For (INT I = 0; I <digits. Size (); I ++) if (digits [I]! = B. digits [I]) return false; return true ;}// binary search. Int binarysearch (int n, string p) {int down = 1, up = 1000000000, middle; integer target = INTEGER (p); While (down <= up) {middle = (down + up)/2; integer m = INTEGER (middle); integer TMP = INTEGER (1); For (INT I = 1; I <= N; I ++) TMP * = m; If (TMP = target) return middle; else if (TMP <target) Down = middle + 1; elseup = middle-1 ;}} int main (int ac, char * AV []) {int N; string P; while (CIN> N> P) cout <binarysearch (n, p) <Endl; return 0 ;}