Умная вещь, которую нужно сделать, - это создать формулу, доказать ее с помощью рекурсии, а затем применить ее.
На самом деле сначала я не буду использовать рекурсию, но некоторые простые математические вычисления: своего рода теория вероятностей / комбинаторная теория, хотя их нетслучайные события здесь.
Учитывая количество цифр, скажем, две, число чисел ниже, которые не имеют никаких 1, всегда будет 9 к степени числа цифр, таким образом, для 00 до 9981 таких номеров.Таким образом, есть 19, которые делают (100-81).
В каждом случае мы будем считать количество чисел, которые не содержат ни одного.
5394, например, является суммой диапазонаОт 0 до 4999 и сумма от 5000 до 5394.
Сумма до 4999 является произведением цифр: 4 * 9 * 9 * 9 (0-4, 0-9, 0-9, 0-9 за исключением 1 в каждом случае)
Сумма от 5000 до 5394 совпадает с суммой от 000 до 394: разделить 000 до 299, от 300 до 394. Таким образом, 2 * 9 * 9 + работает от 00 до 94что составляет 8 * 9 плюс 90-94, что на 4 больше.
Таким образом, от 0 до 5394 есть 4 * 9 * 9 * 9 (2916) + 2 * 9 * 9 (162) + 8 * 9(72) + 4 = 3154
Вычтите из нашего основного числа + 1 (5395), и мы получим решение 2241. (Мы вычитаем из 5395, потому что мы посчитали от 0 до 5394, что составляет 5395 чисел)
Решение - взять каждую цифру> 1, вычесть одну и умножить на 9 для каждой цифры, которая появляется после нее.Если число равно 1, мы не вычитаем одно.Если число равно нулю, мы пропускаем.
Если мы встречаем 1, мы пропускаем все оставшиеся цифры.Таким образом, если наше число 52136, после достижения 1 мы пропускаем все остальные.(У нас будет счет до 52099, и больше не будет).Мы по-прежнему используем целое число для вычитания в конце.
Для последней цифры: Если до сих пор не было 1 цифры, мы добавляем последнюю цифру и добавляем 1, еслиэто 0. Таким образом, добавьте 4 для 5394, 1 для 5390, ничего для 5216, потому что он содержит 1 перед последней цифрой, но все равно добавьте 1 для 5391 (представляющий 5390, который не был включен в более ранний счет).
Затем вычтите эту сумму из нашего числа + 1 и вычтите еще 1 (потому что я от 0 до N, что составляет N + 1 чисел)
n = 29, таким образом, 1 * 9 + 9 = 18. Вычтитеиз n + 1, и мы получаем 12, как вы хотели.
n = 100: 1 * 9 * 9 = 81. Вычтите из 101 (наше число содержит 1), чтобы получить 20.
Вот твоя формула.Теперь перейдите и запрограммируйте его.
** Немного альтернативный способ **
"рекурсивным" способом: мы вычисляем число чисел, которые не содержат 1, строго меньше нашего значения (не считая этого) давайте назовем это именем, f (N)
f (10N) всегда равно f (N) * 9. Мы можем легко это доказать: есть f (N) чисел, которые меньше чемЗатем N умножьте их на 10 и добавьте в каждую из цифр 0 и 2-9 в конце 9 разных цифр.
f (10N + m), где 0 <= m <= 9 - одна цифраиспользует формулу добавления последней цифры, поэтому, если N содержит 1 цифру, это просто f (N) * 9, иначе добавьте 0 для m = 0 1 для m = 1 и m-1 для любого другого. </p>
f (394858) = 7 + 9 * f (39485) f (573940) = 9 * f (57394) f (491029) = 9 * f (49102) (содержит 1 цифру)
Your "f"функция может возвращаться и должна содержать 2 фрагмента информации: содержит ли она 1 цифру и возвращаемое значение.Базовый случай состоит из одной цифры
f (N) - это число чисел, строго меньше N, которые не содержат 1. Чтобы получить число, которое нужно, вычтите это из N и добавьте 1, если наше числосамо содержит 1.
f (10N + M) = 9 * f (N), если N содержит 1, 9 * f (N) + f (M), если N не содержит 1.
f (0) = 0 f (1) = 1 f (M) для 2-9: M-1 f (10) = 9 * f (1) = 9 f (100) = 9 * f(10) = 81 решение - это 100 - 81 + 1 (потому что 100 содержит 1, мы добавляем единицу), что дает нам 20 f (9) = 8 f (99) = 8 * 9 + 8 = 80 вычесть 80 из 99, чтобы датьмы 19 и не добавляем 1, так как 99 не содержит 1. Теперь давайте попробуем кодирование:
struct res
{
unsigned int numDigs;
bool hasOneDig;
res( unsigned int n, bool h ) : numDigs( n ), hasOneDig( h ) {}
};
res oneDigitCount( unsigned int input )
{
assert( input < 10 );
switch( input )
{
case 0:
return res( 0, false );
case 1:
return res( 1, true );
default:
return res( input-1, false );
}
};
res countNoOnes( unsigned int input )
{
if( input < 10 )
return oneDigitCount( input ); // base case that ends recursion
unsigned int quotient = input / 10;
unsigned int remainder = input % 10;
res result = countNoOnes( quotient ); // recursive
result.numDigs *= 9;
if( !result.hasOneDig )
{
res remainderRes = oneDigitCount( remainder );
result.numDigs += remainderRes.numDigs;
if( remainderRes.hasOneDig ) // or remainder==1
result.hasOneDig = true;
}
return result;
}
unsigned int countNumsContainingOne( unsigned int input )
{
res noOnes = countNoOnes(input);
unsigned int result = input - noOnes.numDigs;
if(noOnes.hasOneDig)
++result; // as this number has a one
return result;
}
Не очень ОО, может быть легко адаптировано для C (замените конструктор на функцию, которая возвращает структуру), нодолжно работать.