Іншою можливістю буде наступна:
Ви починаєте з найбільшого десяткового числа типу "1111111 ... 1111", підтримуваного використовуваним типом даних
Алгоритм передбачає, що вхід менший за це число; інакше доведеться використовувати інший тип даних.
Приклад: при використанні long longви починаєте з числа 1111111111111111111.
- Потім обробіть кожну десяткову цифру зліва направо:
- Спробуйте змінити цифру з 1 на 0.
- Якщо результат все-таки більший за ваш вхід, зробіть зміни (змініть цифру на 0).
- Інакше цифра залишається 1.
Приклад
Input = 10103
Start: 111111
Step 1: [1]11111, try [0]11111; 011111 > 10103 => 011111
Step 2: 0[1]1111, try 0[0]1111; 001111 < 10103 => 011111
Step 3: 01[1]111, try 01[0]111; 010111 > 10103 => 010111
Step 4: 010[1]11, try 010[0]11; 010011 < 10103 => 010111
Step 5: 0101[1]1, try 0101[0]1; 010101 < 10103 => 010111
Step 6: 01011[1], try 01011[0]; 010110 > 10103 => 010110
Result: 010110
Доказ коректності:
У цьому алгоритмі ми обробляємо цифру за цифрою. На кожному кроці є цифри, значення яких уже відомі, і цифри, значення яких ще не відомі.
На кожному кроці ми зондуємо крайню ліву невідому цифру.
Встановлюємо цю цифру на "0", а всі інші невідомі цифри - на "1". Оскільки цифра, що підлягає зондуванню, є найбільш значущою з невідомих цифр, то отримане число - це найбільше можливе число, причому ця цифра дорівнює "0". Якщо це число менше або дорівнює вхідному, цифра, що досліджується, повинна бути "1".
З іншого боку, отримане число менше, ніж усі можливі числа, де зондувана цифра є "1". Якщо отримане число перевищує вхідне, цифра повинна бути "0".
Це означає, що ми можемо обчислити одну цифру на кожному кроці.
C код
(Код С також повинен працювати під C ++):
long long input;
long long result;
long long digit;
... read in input ...
result = 1111111111111111111ll;
digit = 1000000000000000000ll;
while( digit > 0 )
{
if(result - digit > input)
{
result -= digit;
}
digit /= 10;
}
... print out output ...