2010-10-01 5 views
13

Я знаю, что есть способ найти сумму цифр 100! (Или факториал любого другого большого числа) с использованием Python. Но я считаю, что это очень сложно, когда дело доходит до C++, как размер даже LONG LONG недостаточно.Есть ли способ найти сумму цифр 100 !?

Я просто хочу знать, есть ли другой способ.

Я понимаю, что это невозможно, так как наш процессор, как правило, 32 бит. То, что я имею в виду, это какой-то другой сложный метод или алгоритм, который может выполнять то же самое, используя одни и те же ресурсы.

ответ

6

long long не является частью C++. g ++ предоставляет его как расширение.

Arbitrary Precision Arithmetic - это то, что вы ищите. Проверьте псевдокод, указанный на странице вики.

Более того, long long не может хранить такие большие значения. Таким образом, вы можете создать свой класс BigInteger или использовать некоторые сторонние библиотеки, например GMP или C++ BigInteger.

+2

C++ 0x имеет 'long' long', заимствованный из C, который включил его в стандарт более десяти лет назад. – hobbs

6

Если вы имеете в виду проблему Project Euler, то мое чтение состоит в том, что он хочет, чтобы вы написали свою собственную целую библиотеку произвольной точности или класс, который может умножать числа.

Мое предложение состоит в том, чтобы хранить базовые 10 цифр числа в порядке, обратном порядку их записи, потому что в конце концов вам нужно будет преобразовать число в базу 10. Сохранение цифр в обратном порядке делает запись, по-моему, более простой и удобной процедуры добавления и умножения. Затем создайте процедуры добавления и умножения, которые эмулируют, как вы будете добавлять или умножать числа вручную.

+2

Я считаю, что проще использовать вектор целых чисел, каждое из которых использует только половину своих бит (если вы используете 64 разрядное целое число, магазин в каждый элемент состоит только из 32 бит), таким образом вы гарантируете, что в любой из операций не будет переполнения. Затем каждая операция может выполняться сначала в каждом подэлементе, а затем объект может быть нормализован последовательным образом. –

+2

@David Rodríguez - dribeas - Я согласен, что в целом лучше, особенно если важно использовать память или скорость вычислений. Но в этом конкретном случае, если все, что вам нужно, это сумма цифр в базе 10, но вы фактически сохраняете их на какой-либо другой базе, то вам также нужно написать функцию деления или преобразования базы. – Doug

+3

Я не знаю, что такое Project Euler, поэтому, если вы правы, вы можете лучше понять требования к производительности, но IMO, если он просто изучает C++ из Python и использует это как упражнение, он может сделать хуже, чем поместите ASCII-кодированные цифры в строку std ::. Получение алгоритма умножения более важно, чем эффективное представление данных, и знакомый тип, который растет и может быть тривиально представлен, имеет некоторые преимущества. Выполняя эту цифру одновременно, так же легко обрабатывать перенос в алгоритме - нет необходимости резервировать пространство в структуре данных. –

4

В C++ имеется несколько библиотек BigInteger. Просто Google "C++ BigInteger". Но если это проблема программирования, то лучше попробовать реализовать собственную библиотеку BigInteger.

14

Как вы собираетесь найти сумму цифр 100 !. Если вы вычислите 100! сначала, а затем найдите сумму, тогда какая точка. Вам придется использовать некоторую интеллектуальную логику, чтобы найти ее, фактически не вычисляя 100 !. Удалите все коэффициенты из пяти, потому что они только добавят нули. Подумайте в этом направлении, вместо того, чтобы думать о большом количестве. Также я уверен, что окончательный ответ, т. Е. Сумма цифр будет в течение ДЛИННОГО ДОЛГОГО.

Существуют библиотеки C++ с большими int, но я думаю, что здесь основное внимание уделяется алгоритму, а не библиотеке.

+0

Окончательный ответ того, что поместится в 'long long'? Вы можете легко увидеть, что верхняя граница суммы цифр хорошо под 100 * 2 * 10 = 2000, что легко вписывается в «короткий». Между тем, '100!' Составляет 158 цифр (525 бит) или 134 цифры (445 бит) без конечных нулей, поэтому они не будут вписываться в 'long long'! – Gabe

+0

Даже после удаления коэффициентов 10 результат все равно не будет вписываться в «длинный длинный», на огромную сумму - см. Комментарий hobbe в одном из других ответов. Есть форум для людей, которые решили эту проблему и хотят опубликовать свое решение, и практически каждый ответ на этом форуме либо использует библиотеку/язык BigNum, либо создает достаточно хороший эквивалент. – Doug

+0

Почему у этого так много упреков? Это всего лишь принятие желаемого за действительное, я не думаю, что существует реальное решение по этому вопросу. –

0

Вы можете воспользоваться легкой дорогой и использовать perl/python/lisp/scheme/erlang/etc для расчета 100! используя одну из встроенных библиотек bignum или тот факт, что на некоторых языках используется точная целочисленная арифметика. Затем возьмите это число, сохраните его в строке и найдите сумму символов (с учетом «0» = 48 и т. Д.).

Или вы могли бы подумать, что в 100 !, вы получите действительно большое количество с множеством нулей. Если вы вычислите 100! итеративно, рассмотрим деление на 10 каждый раз, когда текущий факторный делится на 10. Я считаю, что это даст результат в диапазоне длинного длинного или чего-то еще.

Возможно, лучшее упражнение - написать свою собственную большую библиотеку. Вы будете нуждаться в этом для некоторых более поздних проблем, если не найдете умных трюков.

+0

Re: Второй абзац: ваше предположение выключено. Факториал слишком быстро развивается. Обычно 64-битный int переполняется между 20! и 21 !. Снимая десятки как можно чаще, вы получаете до 23 !. Есть всего четыре нуля для удаления (10 000), а 22 * ​​23 * 24 - 12 144 - уже более 10 000. – hobbs

+0

Err да. Я просто посмотрел на свой исходный код проблемы 20 эйлера проекта (эта проблема), и я в основном сделал это в сочетании с идеей Абеленки при использовании битового вектора для отслеживания используемых номеров. – Kizaru

+0

Если у вас есть библиотека bignum, вы можете обычно использовать 'div' и' mod', что почти всегда будет быстрее, чем преобразование в строку и использование этих цифр. Например: 'digitSum = 0; while (n! = 0) {digitSum + = n.mod (10); n = n.div (10); } ' – Olathe

15

Используйте цифровую матрицу со стандартным методом умножения на бумаге.Например, в C  :

#include <stdio.h> 

#define DIGIT_COUNT 256 

void multiply(int* digits, int factor) { 
    int carry = 0; 
    for (int i = 0; i < DIGIT_COUNT; i++) { 
    int digit = digits[i]; 
    digit *= factor; 
    digit += carry; 
    digits[i] = digit % 10; 
    carry = digit/10; 
    } 
} 

int main(int argc, char** argv) { 
    int n = 100; 

    int digits[DIGIT_COUNT]; 
    digits[0] = 1; 
    for (int i = 1; i < DIGIT_COUNT; i++) { digits[i] = 0; } 

    for (int i = 2; i < n; i++) { multiply(digits, i); } 

    int digitSum = 0; 
    for (int i = 0; i < DIGIT_COUNT; i++) { digitSum += digits[i]; } 
    printf("Sum of digits in %d! is %d.\n", n, digitSum); 

    return 0; 
} 
+4

Возможно, я опаздываю в комментировании, но все же я не знаю, почему OP не принял это как решение. Это просто, чисто, изобретательность в лучшем случае (в основном, при умножении бумаги на каждую цифру в качестве элемента массива, чтобы заботиться о проблемах с бонусом. Когда другие участвуют в использовании библиотек bignum и произвольной точности, это решение выделяется для своей простоты, но удивительно (Isee это было бы решение O (N)), почему это так тихо незаметно, без комментариев, когда люди комментируют многие тривиальные «только ради этого» ответы в целом на SO. Sad – goldenmean

+0

очень впечатляющее решение. :) –

5

Заметим, что умножение любого числа на или не изменяет сумму цифр.

После того, как вы узнаете, что, видно, что умножение на 2 и 5, или от 20 до 50 лет, также не изменяет сумму, так как 2x5 = 10 и 20x50 = 1000.

Затем обратите внимание, что в любое время, когда ваше текущее вычисление заканчивается на 0, вы можете просто делить на 10 и продолжать вычислять факториал.

Сделайте еще несколько замечаний о ярлыках, чтобы устранить цифры от 1 до 100, и я думаю, что вы могли бы подогнать ответ в стандартные ints.

+2

Я должен отменить этот ответ. После работы с несколькими «ярлыками» сегодня, я не нашел приемлемого решения. Я рассмотрел опубликованные решения для Euler # 20, и все, казалось, делали это с библиотекой BigNum того или иного типа. Я больше не уверен, что эта проблема может быть решена в UInt64. Может ли кто-нибудь сказать мне, что это может быть? – abelenky

+0

100 факториал длиной 158 цифр, с 24 обратными нулями (источник [WolframAlpha] (http://www.wolframalpha.com/input/?i=100%21)). Удаление нулей не поможет, так как [даже при удалении нулей требуется 446 бит] (http://www.wolframalpha.com/input/?i=Ceil%5BLog%5B2%2C+100%21 % 2F10% 5E24% 5D% 5D). – Olathe

1

Ничего в проекте Euler не требует больше __int64.

Я хотел бы предложить, пытаясь сделать это, используя базу 10000.

+2

Python очень, очень умный, чтобы иметь возможность сделать это. Потрясающе, что мой 3-летний ноутбук возвращает 'print sum (map (int, str (math.factorial (30000))))' как '511470' всего за несколько секунд. – Potatoswatter

Смежные вопросы