Problem:
Given a positive integer N, evaluate a minimum positive integer M (M> 1) so that the decimal representation of N * M contains only 1 and 0.
Solution:
There is no direct mathematical method to help us directly obtain the M value, so we can only search. Because product N * M has obvious features relative to M, the search space is much smaller, so we search product N * M. If the N * M result has K digits, We need to cycle 2 ^ K times. We found that K results can easily exceed 40, so the running time is still quite long.
The coequal operation has an equivalence relationship. mod N = I (0 <= I <N) Forms N equivalence classes and divides positive integer sets. For each equivalence class, we only need to judge whether the smallest element plus 10 ^ K can be divisible by N, so that the search space is reduced from 2 ^ K times to (K-1) * N step, the value of N is generally much smaller than the value of M. But it requires O (N) space complexity.
We can prove that for any N, there must be M, so that the product of N * M in decimal format is only 0 and 1. The proof process can be seen in the fact that both M and N * M have a large number of digits, so we use a large integer to represent M and N * M. Because N is a big integer, N cannot be a big integer, that is, the value of N should be less than 1 million.
[Cpp]
# Include <iostream>
# Include <cstring>
Using namespace std;
// Big Integer type
# Define MAXLEN 100
Struct HP {int len, s [MAXLEN];};
Void PrintHP (const HP & x)
{
For (int I = x. len; I> = 1; I --)
Cout <x. s [I];
}
// Convert the string to a large integer
Void Str2HP (const char * s, HP & x)
{
X. len = strlen (s );
For (int I = 1; I <= x. len; I ++)
X. s [I] = s [x. len-I]-'0 ';
If (x. len = 0)
{
X. len = 1;
X. s [1] = 0;
}
}
// Addition of large Integers
Void Plus (const HP a, const HP B, HP & c)
{
Int I; c. s [1] = 0;
// The addition operation of big integers a and B and the carry operation of Result c
For (I = 1; I <= a. len | I <= B. len | c. s [I]; I ++)
{
If (I <= a. len) c. s [I] + = a. s [I];
If (I <= B. len) c. s [I] + = B. s [I];
C. s [I + 1] = c. s [I]/10; c. s [I] % = 10;
}
// Exit the loop because c. s [I] = 0.
C. len = I-1;
If (c. len = 0) c. len = 1;
}
// Subtraction of large Integers
Void Subtract (const HP a, const HP B, HP & c)
{
Int I, j;
For (I = 1, j = 0; I <= a. len; I ++)
{
// J indicates whether to borrow a bid from a high position
C. s [I] = a. s [I]-j;
If (I <= B. len) c. s [I]-= B. s [I];
If (c. s [I] <0)
{
// Borrow from the high bid and add 10
J = 1;
C. s [I] + = 10;
}
Else j = 0;
}
C. len = a. len;
While (c. len> 1 &&! C. s [c. len]) c. len --;
}
// Compare large Integers
Int HPCompare (const HP & x, const HP & y)
{
If (x. len> y. len) return 1;
If (x. len <y. len) return-1;
Int I = x. len;
While (I> 1 & (x. s [I] = y. s [I]) I --;
Return x. s [I]-y. s [I];
}
// Multiplication of large Integers
Void Multi (const HP a, const HP B, HP & c)
{
Int I, j;
// Assign an initial value to the multiplication result to facilitate subsequent + = operations
C. len = a. len + B. len;
For (I = 1; I <= c. len; I ++) c. s [I] = 0;
For (I = 1; I <= a. len; I ++)
For (j = 1; j <= B. len; j ++)
C. s [I + J-1] + = a. s [I] * B. s [j];
// Carry the operation result
For (I = 1; I <c. len; I ++) {c. s [I + 1] + = c. s [I]/10; c. s [I] % = 10 ;}
// Carry the highest bit
While (c. s [I]) {c. s [I + 1] = c. s [I]/10; c. s [I] % = 10; I ++ ;}
// Ensure that the maximum bit is not 0
While (I> 1 &&! C. s [I]) I --;
C. len = I;
}
// Division of large Integers
Void Divide (const HP a, const HP B, HP & c, HP & d)
{
Int I, j;
// Use the remainder d to store the first I-bit data of divisor a, and subtract the divisor B multiple times to obtain the operator c
D. len = 1; d. s [1] = 0;
For (I = a. len; I> 0; I --)
{
If (! (D. len = 1 & d. s [1] = 0 ))
{
// I does not move one bit, and the remainder d is also shifted.
For (j = d. len; j> 0; j --)
D. s [j + 1] = d. s [j];
D. len ++;
}
D. s [1] = a. s [I];
C. s [I] = 0;
// The subtraction operation can be performed only when the remainder d is greater than the divisor B.
While (j = HPCompare (d, B)> = 0)
{
Subtract (d, B, d );
C. s [I] ++;
If (j = 0) break;
}
}
C. len = a. len;
While (c. len> 1 & c. s [c. len] = 0)
C. len --;
}
// Shifts decimal places to the right
Void RightShift (HP & x, int k)
{
For (int I = 1; I <= x. len-k; I ++)
X. s [I] = x. s [I + k];
X. len-= k;
If (x. len <= 0)
{
X. len = 1;
X. s [1] = 0;
}
}
// Decimal left shift
Void LeftShift (HP & x, int k)
{
Int I;
For (I = x. len; I> = 1; I --)
X. s [I + k] = x. s [I];
For (I = k; I> = 1; I --)
X. s [I] = 0;
X. len + = k;
}
# Define MAXREM 1000000
HP rem [MAXREM];
Int main ()
{
Int I, j, k, N;
Char str [MAXREM];
HP one, tmp;
One. len = 1; one. s [1] = 1;
While (cin> str)
{
N = atoi (str );
If (N> MAXREM)
{
Printf ("ERROR: N (% d) is too large", N );
Continue;
}
// Clear the remainder information array
For (I = 0; I <N; I ++)
Rem [I]. len = 0;
// Initialize the unique single digit 1
Rem [1] = one;
// I indicates the I bit of N * M found, and j indicates (10 ^ I) % N
For (I = 1, j = 10% N; rem [0]. len = 0; I ++, j = (j * 10) % N)
{
// Tmp indicates a large integer of 10 ^ N
Tmp = one;
LeftShift (tmp, I );
// If the array does not have the same number as tmp
If (rem [j]. len = 0)
Rem [j] = tmp;
For (k = 1; k <N; k ++)
{
// Traverses the remainder information array. If a new remainder is generated
Int u = (j + k) % N;
// To prevent the newly added 10 ^ N from being calculated, add the condition rem [k]. len <= I
If (rem [k]. len & rem [k]. len <= I
& Rem [u]. len = 0)
Plus (tmp, rem [k], rem [u]);
If (u = 0)
Break;
}
} Www.2cto.com
Str2HP (str, tmp );
Cout <"N * M :";
PrintHP (rem [0]);
HP d;
Divide (rem [0], tmp, tmp, d );
Cout <endl <"M :";
PrintHP (tmp );
Cout <endl;
}
}
Author: linyunzju