Сума дільника від факторизації потужності


11

Завдання полягає в обчисленні дільника суми числа, враховуючи його просте множення.

Вхідні дані

Два масиви (або щось еквівалентне) довжиною n , один містить основний коефіцієнт, а другий містить відповідний показник.

Вихідні дані

Сума всіх дільників (включаючи саме число).

Приклад

Число 240 має 2, 3 і 5 як прості коефіцієнти з 4, 1 і 1 як відповідні показники. Очікуваний вихід тоді складе 744.

Input: [2,3,5] [4,1,1]
Output: 744

Оцінка балів

Найкоротший код у байтах виграє!

Якщо складність часу виконання вашого рішення становить O (сума показників), а не O (добуток експонентів), ваш бал може бути помножений на 0,8.


Тут було розміщено подібне запитання , але це не було викликом. Я думаю, що проблему цікаво, що варто пограти в гольф.

Переможця вибиратимуть ці вихідні


Чи завжди масив основного фактора повинен бути першим, а масив експонентів другим, чи можна вважати, що масиви вводяться навпаки?
Sp3000

Ви можете припустити, що будь-який формат введення подібний до запропонованого
Moartem,

Неможливо знайти його зараз, але я думаю, що це чи щось подібне є на projecteuler.net
flawr

Відповіді:


3

Pyth, 13 байт * 0,8 = 10,4

*Fms^LhdhedCQ

Демонстрація.

Ця відповідь працює дещо інакше, ніж вище. Для того, щоб обчислити суму факторів простих сил числа, замість того, щоб використовувати арифметичну формулу, коефіцієнти експлікаційно будуються та підсумовуються.

Так , наприклад, на [прем'єр, показник] пари [2, 4], ми відображаємо 2 ^ xнад 0, 1, 2, 3, 4, даючи [1, 2, 4, 8, 16], який потім підсумовується до 31.

Потім результати множать разом і друкують.

Якщо експоненція буде виконана належним чином, або якщо є проміжне кешування результатів, це буде O(sum of exponents).


Незалежно від реалізації, я не думаю, що можливо обчислити першу n потужність a за O (n) час, якщо ви не припускаєте, що множення є O (1).
Денніс

@Dennis Ну, терміни вищого порядку домінують, тому, ймовірно, буде час перемноження найвищого порядку, що є, O(n)якщо ми можемо вважати, що база є постійною.
isaacg

9

CJam, 15 байт * 0,8 = 12

q~.{_@)#(\(/}:*

Спробуйте в Інтернеті . Порядок введення спочатку - це список експонентів, потім - список простих чисел (-3 байти завдяки @Dennis) .

(p, e)Знайдіть для кожної пари простий показник

(p^(e+1) - 1)/(p - 1)

то знайдіть добуток усього цього. Наприклад, на 240 це було б

(1 + 2 + 4 + 8 + 16)(1 + 3)(1 + 5) = 31 * 4 * 6 = 744

Залежно від способу здійснення експоненції це може бути кращим, ніж O(sum of exponents).


6

APL, 18 13 байт * 0,8 = 10,4

×/(1-⊣×*)÷1-⊣

Це створює діадичний функціональний потяг, який приймає масив факторів зліва та експоненти праворуч.

×/             ⍝ Vector product of
  (1-⊣×*)      ⍝ each factor^(exponent+1)-1
         ÷1-⊣  ⍝ divided by factor-1

Спробуйте в Інтернеті . Зауважте, що це той самий підхід, що й дивовижно спритна відповідь Sp3000 на CJam .

Збережено 5 байт завдяки Деннісу!


2

TI-BASIC, 17 байт * 0,8 = 13,6

Також використовується метод Sp3000, хоча я знайшов його самостійно. Бере один список з Input та один з домашнього екрану.

Input E
prod(AnsAns^∟E-1)/prod(Ans-1

Використання prod (удвічі менше, оскільки дозволяє безкоштовно використовувати відкриті дужки. Зауважте, що ця відповідь не підтримує порожні масиви, оскільки в TI-BASIC немає порожніх масивів.


2

Хаскелл, 38 * 0,8 = 30,4

product$zipWith(\p e->(p*p^e-1)/(p-1))

Використання:

product$zipWith(\p e->(p*p^e-1)/(p-1)) [2,3,5] [4,1,1]
744.0

Анонімна функція переходить (p,e)до суми дільника за p^eдопомогою суми геометричних рядів. Складання двох списків разом із цим як приєднання та взяття продукту дає результат.

Я не зміг знайти нічого коротшого, ніж арифметичний вираз

(p*p^e-1)/(p-1)
sum$map(p^)[0..e]

Можливо, є спосіб позбутися від (\p e->_).

Визначення функції Infix дає однакову довжину (38):

p%e=(p*p^e-1)/(p-1)
product$zipWith(%)

2

C ++, 111 80 77 байт * 0,8 = 61,6

int g(int*p,int*e,int n){return n?g(p+1,e+1,n-1)*(pow(*p,*e-1)-1)/(*p-1):1;}

Це обчислює (p ^ (e + 1) -1) / (p-1) і рекурсивно множує всі фактори. Виявив це сам рік тому.

Дякую за допомогу, повністю забув про булеве використання стилю c ++.


1
n==0спрощує !n- або ви можете змінити результати та просто скористатисяn
Toby Speight

2

Матлаб, 53

function t=f(x,y)
s=1:prod(x.^y);t=s*~mod(s(end),s)';

Приклад:

>> f([2 3 5], [4 1 1])
ans =
   744

Схоже, ви можете додати бонус 0,8
Moartem

@Moartem Дякую! Але я не впевнений у цьому. Я обчислюю число, sа потім перевіряю всі можливі дільники від 1до s. Отже, це (принаймні) O (s), яке, ймовірно, між O (сума показників) і O (добуток експонентів)
Луїс Мендо,

Так, це навіть більше, ніж O (добуток експонентів)
Moartem

1

Пітон 2,156

from itertools import*
from operator import*
i=input()
print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])))

Вхідні дані

[[2,3,5],[4,1,1]]

Вихідні дані

744

Пояснення

Ця програма отримує список із 2 списків: фактори та показники.

i=input() # Receive list of 2 lists: i[0] for factors i[1] for exponents

Потім його створюють список усіх можливих комбінацій списку експонентів.

[x+1 for x in i[1]] # [4,1,1]->[5,2,2] (to include last element)
map(range,[x+1 for x in i[1]]) # [[0, 1, 2, 3, 4], [0, 1], [0, 1]]
product(*map(range,[x+1 for x in i[1]])) # [(0, 0, 0), (0, 0, 1), ..., (4, 1, 1)]

і пов'язуйте його з факторами:

zip(i[0],p) for p in product(*map(range,[x+1 for x in i[1]])) # [[(2, 0), (3, 0), (5, 0)], ..., [(2, 4), (3, 1), (5, 1)]]

Обчисліть коефіцієнти до потужності показників:

 [a**b for a,b in zip(i[0],p)]for p in product(*map(range,[x+1 for x in i[1]])) # [[1, 1, 1], ..., [16, 3, 5]]

і помножити кожен список (це дає нам усі дільники):

reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])) # [1, 5, 3, 15, ..., 240]

Нарешті підсумовуйте всі списки та друкуйте:

print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]]))) # 744

Чи можете ви коротко пояснити, що робить ваш код (як я не знайомий з python), щоб я міг судити про складність вашого коду?
Moartem

Це розумний підхід, але складність полягає в досягненні експонентів
Moartem

@Moartem Так, я не витратив багато часу на зменшення складності
TheCrypt

1

Пітон 3, 134 120 117

Введення: два масиви, розділені комами, розділені комою.

Приклад:

(2,3,7,11),(4,2,3,2)
21439600
from functools import*
a=eval(input())
print(reduce(int.__mul__,(sum(x**j for j in range(y+1))for x,y in zip(*a)),1))

За допомогою NumPy можна скоротити до 100 байт:

import numpy
a=eval(input())
print(numpy.product([sum(x**j for j in range(y+1))for x,y in zip(*a)]))

1
Для першого прикладу, просто так ви знаєте, замість того, щоб імпортувати operatorдля використання mulодин раз, ви можете використовувати, float.__mul__щоб зберегти купу байтів.
Каде

1

Желе, не конкуруючий

Ця відповідь не є конкурентоспроможною, оскільки виклик передує створенню желе.

5 байт (без бонусу)

*PÆDS

Спробуйте в Інтернеті!

Як це працює

*PÆDS    Main link. Left input: p (prime factors). Right input: e (exponents).

*        Elevate the prime factors to the corresponding exponents.
 P       Take the product of all powers.
  ÆD     Find all divisors of the product.
    S    Compute the sum of the divisors.

7 байт (5,6 байт після бонусу)

*‘}’:’{P

Як це працює

×*’:’{P  Main link. Left input: p (prime factors). Right input: e (exponents).

 *       Elevate the prime factors to the corresponding exponents.
         This yields p ** e.
×        Multiply the prime factors with the corresponding powers.
         This yields p ** (e + 1).
  ’      Decrement the resulting products.
         This yields p ** (e + 1) - 1.
    ’{   Decrement the prime factors.
         This yields p - 1.
   :     Divide the left result by the right one.
         This yields (p ** (e + 1) - 1) / (p - 1).
      P  Take the product of all quotients.

Спробуйте в Інтернеті!


1

APL, 12 байт * 0,8 = 9,6

×/1++/¨⎕*⍳¨⎕

Це читає два списки з клавіатури, спочатку експоненти, тобто:

      ×/1++/¨⎕*⍳¨⎕
⎕:
      4 1 1
⎕:
      2 3 5
744

Пояснення:

  • : читати список з клавіатури (експоненти)
  • ⍳¨: для кожного номера у списку генеруйте список [1..n].
  • ⎕*: прочитайте ще один список з клавіатури (праймеди) та підніміть кожний простір до кожного із показників у відповідних списках
  • +/¨: підсумовуйте кожен список
  • 1+: додайте по одному до кожного результату, щоб компенсувати пропущені x^0у кожному зі списків
  • ×/: взяти добуток результатів

1

Ракетка (схема), 65 * 0,8 = 52 байти

Така ж арифметика, як і всі інші

(λ(x y)(foldl(λ(m n o)(*(/(-(expt m(+ n 1))1)(- m 1))o))1 x y))

Пояснення:

(λ (x y)    ;defines anonymous function with two inputs
    (foldl    ;recursively applies the following function to all elements of the lists given to an argument given (foldl function argument lists lists lists...)
        (λ (m n o) (* (/ (- (expt m (+ n 1)) 1) (- m 1)) o))    ;an anonymous function representing the same arithmetic used in the CJam answer, then multiplying it with our incrementor
        1 x y))    ;the incrementor argument is 1, and the input lists are the ones provided into the original function

0

Пітон 2, 80 байт * 0,8 = 64

Це передбачає, що введення надходить один за одним. Дотримується тієї самої формули, що описана у відповіді CJam Sp3000.

print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(input(),input())],1)) 

Якщо це не дозволено, я використовую це як рішення, яке отримує бал 84 байти * 0,8 = 67,2. Введення має бути відокремлене комою, тобто [2,3,5],[4,1,1].

k=input()
print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(k[0],k[1])],1))

Psst. Гей! Це можливе рішення в Symbolic, над чим я працюю:Ƥ(П([~-(x**-~y)/~-xϝx,yϊʐ(Ί,Ί)],1))


0

Математика, 40 байт

Total[Outer@@{*}~Join~(#^0~Range~#2),3]&

Не використовуючи жодної з вбудов, які мають справу з дільниками, відмежовуватись від іншого математичного рішення в потоці.

Введення (з прикладу) [{2, 3, 5}, {4, 1, 1}]


0

Perl 5, 96 байт

Очевидно, це неприбутковість, але я вирішив написати це для розваги.

Це підпрограма:

{($b,$e)=@_;$s=1;map$s*=$b->[$_]**$e->[$_],0..@$b-1;$_=1x$s;for$j(1..$s){$i+=$j*/^(.{$j})*$/}$i}

Дивіться це в дії таким чином:

perl -e'print sub{...}->([2,3,5],[4,1,1])'

Як це працює:

  • ($b,$e)=@_читає вхідні масиви $b(бази) та $e(експоненти).
  • $s=1 ініціалізує продукт.
  • map$s*=$b->[$_]**$e->[$_],0..@$b-1множиться $sна послідовні сили-експоненти. Тепер $s- складене число.
  • $_=1x$sмножини, що $_дорівнюють ряду одиниць, $sдовгі. $iініціалізується на 0.
  • for$j(1..$s){$i+=$j*/^(.{$j})*$/}намагається, на кожне число $jвід 1 $sдо, розбити $_, коли $jсимволи повторюються будь-яку кількість разів. Якщо він може, то $jділиться $sі /^(.{$j})*$/дорівнює 1 (інакше це 0), а $iдодається до $j. Таким чином, ми додамо до $iкількості розділів в рівній за розмірами розділі $_. Як зазначає Омар Е. Пол ,$i це число, якого ми шукаємо.
  • $iв кінці повертається $i.

0

J, 14 байт * 0,8 = 11,2

[:*/(^>:)%&<:[

Використання

   f =: [:*/(^>:)%&<:[
   2 3 5 f 4 1 1
744
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.