주어진 크기의 아벨 리안 그룹 계산


14

배경

지난번 에는 주어진 크기의 그룹을 세었습니다 . 이는 사소한 문제가 아닙니다.

이번에는 Abelian 그룹 , 즉 정류 작업을 수행하는 그룹 만 계산 합니다. 공식적으로, 그룹 (G *)은 아벨이면 X * Y = X * Y 모두에 대한 X, YG .

이 방법으로 문제가 훨씬 간단 해 지므로 효율적으로 계산할 것입니다.

직무

음이 아닌 정수를받는 프로그램이나 함수를 작성 N 입력 지문 또는 복귀 명령의 비 동형 아벨 군의 개수 N이 .

그룹 수를 계산하는 한 가지 방법 – A (n)으로 표시 –은 다음을 관찰하는 것입니다.

  • A (0) = 0

  • 경우 p는 소수이고, A (P는 K가 ) 의 정수 파티션의 수와 동일한 K . (참조 OEIS A000041 )

  • 만약 N = MK 하고, mk는 동일 프라임이고, A (N) = A (m) A (K) .

이 방법이나 다른 방법으로 A (n) 을 계산할 수 있습니다 .

테스트 사례

Input               Output
0                   0
1                   1
2                   1
3                   1
4                   2
5                   1
6                   1
7                   1
8                   3
9                   2
10                  1
11                  1
12                  2
13                  1
14                  1
15                  1
16                  5
17                  1
18                  2
19                  1
20                  2
4611686018427387904 1300156
5587736968198167552 155232
9223371994482243049 2

( OEIS A000688 에서 가져옴 )

추가 규칙

  • 충분한 시간, RAM 및 입력을 보유 할 수있는 레지스터 크기가 주어지면 코드는 이론적으로 임의의 큰 정수에서 작동해야합니다.

  • 코드는 모든 정수 사이에 작동해야한다 02 63 일 - 내 컴퓨터 10 분 (인텔 i7-3770, 16 지브 RAM, 페도라 21)에서의 마무리.

    답변을 제출하기 전에 마지막 세 가지 테스트 사례에 대한 코드 시간을 확인하십시오.

  • Mathematica와 같은이 작업을 사소한 내장 기능 FiniteAbelianGroupCount은 허용되지 않습니다.

  • 숫자의 정수 파티션이나 목록의 파티션을 반환하거나 계산하는 내장 기능은 허용되지 않습니다.

  • 표준 규칙이 적용됩니다.


Pyth의 주요 인수 분해 시스템은이 과제에 비해 너무 느립니다.이를 해결해야합니다.
isaacg 2016 년

답변:


3

CJam ( 39 38 바이트)

qimF{~M\{_ee{~\)<1b}%1+a\+}*0=1be&}%:*

온라인 데모

이는 소인수 분해 ( mF)를 찾은 다음 각 거듭 제곱의 파티션을 계산하고 제품을 취하는 제안 된 라인을 따릅니다 .

두 가지 특별한 경우가 있습니다 mF: 그것은 요인 0으로 0^11같이1^1 . 후자는 특별한 대우를 필요로하지 않습니다. 크기가 1 인 Abelian 그룹과 파티션이 1입니다. 그러나 0은 특별한 경우가 필요합니다.

파티션 카운팅은 부분 으로 A008284(n, k)의 파티션 수에 대한 반복을 사용합니다 . OEIS에서 그것은됩니다 로 제공nk

T(n, k) = Sum_{i=1..k} T(n-k, i), for 1<=k<=n-1; T(n, n) = 1 for n >= 1.

하지만 합계를에서까지 범위로 생각하는 것이 더 유용하다고 생각 1합니다 min(k, n-k).

해부

q~              e# Parse input into an integer
mF              e# Factorise it
{               e# For each factor p^a
  ~             e#   Split the array [p a]
                e#   The following lines count partitions of a
                e#   (Note: they would be buggy if a were ever 0, but it isn't)
  M\{           e#   Starting with a table of zero rows, repeat a times
    _ee         e#     Copy table and pair each row with its index
    {~\)<1b}%   e#     Extract that prepended index and use it to sum for each j
                e#     the first jth items of row j
    1+          e#     Append a 1 for P(i, i)
    a\+         e#     Prepend the new row to the table (which is stored in reverse)
  }*
  0=1b          e#   Sum the elements in the latest (first) row

  e&            e#   If p was 0 then replace with 0
}%
:*              e# Take the product

5

CJam, 50 49 47 43 바이트

ri_mF{1=_L{1$0>{,f{):X-Xj}:+}{;!}?}2j}%:*e&

CJam의 내장 mF인수 분해 및이 Python 파티션 번호 함수의 메모 된 포트를 사용합니다.

p=lambda n,x:n==0 or n>0and sum(p(n+~a,a+1)for a in range(x))

또는 ungolfed :

def p(n, x): # Call like p(n, n). n is number remaining, x is max part size
  if n > 0:
    return sum(p(n-a-1,a+1)for a in range(x))
  else:
    return (n==0)

@RetoKoradi의 답변과 마찬가지로 마지막 사례는 오프라인 통역사에서 약 17 초가 걸리므로 CJam이 숫자를 분해하는 데 시간이 오래 걸리기 때문입니다. 따라서이 온라인 테스트 스위트에서 제외했습니다 .

전체 설명

[Main body]
ri                                Read input and convert to int
  _          e&                   Logical AND input with final result to special case 0 
   mF                             Factorise input into [base, exponent] pairs
     {...}%                       Map, converting each pair to a partition number
           :*                     Take product

[Pair -> partition]
1=_                               Get exponent and copy (n,x in above Python)
   L                              Initialise empty cache
    {                       }2j   Memoise with 2 arguments
     1$0>                         Check if n > 0
         {            }{  }?      Execute first block if yes, else second block
                        ;!        Return (n == 0)
          ,f{      }              For each a in range(x) ...
             ):X-Xj               Call p(n-a-1,a+1) recursively
                    :+            Sum the results

4

매스 매 티카, 96 94 88 바이트

f=1##&@@#&;f[SeriesCoefficient[1/f[1-x^Range@#],{x,0,#}]&/@Last/@FactorInteger@#]Sign@#&

나는 Mathematica에 능숙하지는 않지만 시도해 볼 것이라고 생각했습니다. -6 바이트에 대한 @ MartinBüttner에게 감사합니다.

정수 파티션에 대해 생성 함수 공식을 사용합니다.


3

CJam, 58 바이트

li_mF{1=_L{_1>{_2$<{\;_j}{\,f{)_@\-j}:+}?}{;;1}?}2j}%:*\g*

온라인으로 사용해보십시오

가장 최근의 테스트 예제는 온라인 통역사에서 영원히 (또는 적어도 기꺼이 기다릴 것보다 더 오래) 걸리지 만 랩톱에서 CJam의 오프라인 버전으로 17 초 안에 완료됩니다. 다른 모든 테스트 예제는 거의 즉각적입니다.

이것은 CJam mF연산자를 사용하여 지수로 주요 인수 분해를 제공합니다. 결과는 각 지수에 대한 파티션 수의 곱입니다.

코드의 주요 부분은 파티션 수를 계산하는 것입니다. 메모와 함께 재귀를 지원 하는 연산자를 사용하여 wikipedia 페이지 에서 재귀 알고리즘을 구현했습니다 j.

설명:

li    Get input and convert to int.
_     Make a copy to handle 0 special case at the end.
mF    Factorization with exponents.
{     Loop over factors.
  1=    Take exponent from [factor exponent] pair.
  _     Repeat it, recursive calls are initiated with p(n, n).
  L     Empty list as start point of memoization state.
  {     Start recursive block. Argument order is (m, n), opposite of Wikipedia.
    _1>   Check for n > 1.
    {     Start n > 1 case.
      _2$   Copy both m and n.
      <     Check for n < m.
      {     n < m case.
        \;    Pop m.
        _     Copy n.
        j     Make the p(n, n) recursive call.
      }     End n < m case.
      {     Main part of algorithm that makes recursive calls in loop.
        \,    Generate [0 1 ... m-1] range for k.
        f{    Start loop over k.
          )     Increment, since k goes from 1 to m.
          _     Copy k.
          @\    Rotate n to top, and swap. Now have k n k at top of stack.
          -     Subtract, now have k n-k at top of stack.
          j     Make the p(n-k, k) recursive call.
        }     End loop over k.
        :+    Sum up all the values.
      }?    Ternaray operator for n < m condition.
    }     End n > 1 case.
    {     n <= 1 case.
      ;;1   Pop m, n values, and produce 1 as result.
    }?    Ternary operator for n > 1 condition.
  }2j   Recursive call with memoization, using 2 values.
}%    End loop over factors.
:*    Multiply all values.
\     Swap original input to top.
g     Signum.
*     Multiply to get 0 output for 0 input.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.