Đếm các nhóm Abelian có kích thước nhất định


14

Lý lịch

Thời gian qua, chúng tôi đã tính các nhóm có kích thước nhất định , đây là một vấn đề không hề nhỏ.

Lần này, chúng tôi sẽ chỉ tính các nhóm Abelian , tức là các nhóm có hoạt động giao hoán. Chính thức, một nhóm (G, *) là Abel nếu x * y = y * x cho cho tất cả x, y trong G .

Vấn đề trở nên đơn giản hơn nhiều theo cách này, vì vậy chúng tôi sẽ tính chúng một cách hiệu quả.

Bài tập

Viết chương trình hoặc hàm chấp nhận số nguyên n không âm làm đầu vào và in hoặc trả về số lượng các nhóm Abel không đẳng cấu của đơn hàng n .

Một cách tính số lượng nhóm - mà chúng tôi sẽ biểu thị bằng A (n) - bằng cách tuân thủ các điều sau:

  • A (0) = 0

  • Nếu p là số nguyên tố, A (p k ) bằng số phân vùng nguyên của k . (cfr. OEIS A000041 )

  • Nếu n = mkmk là đồng nguyên tố thì A (n) = A (m) A (k) .

Bạn có thể sử dụng phương pháp này hoặc bất kỳ phương pháp tính A (n) nào khác .

Các trường hợp thử nghiệm

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

(lấy từ OEIS A000688 )

Quy tắc bổ sung

  • Cho đủ thời gian, RAM và kích thước thanh ghi có thể giữ đầu vào, mã của bạn sẽ hoạt động (theo lý thuyết) cho các số nguyên lớn tùy ý.

  • Mã của bạn phải hoạt động cho tất cả các số nguyên trong khoảng từ 0 đến 2 63 - 1 và hoàn thành trong vòng dưới 10 phút trên máy của tôi (Intel i7-3770, RAM 16 GiB, Fedora 21).

    Vui lòng đảm bảo rằng bạn dành thời gian mã cho ba trường hợp kiểm tra cuối cùng trước khi gửi câu trả lời của bạn.

  • Các phần mềm xây dựng tầm thường hóa nhiệm vụ này, chẳng hạn như Mathicala FiniteAbelianGroupCount, không được phép.

  • Tích hợp trả về hoặc đếm các phân vùng nguyên của một số hoặc các phân vùng của danh sách không được phép.

  • Luật tiêu chuẩn được áp dụng.


Hệ thống nhân tố chính của Pyth quá chậm cho thử thách này - tôi cần khắc phục điều đó.
isaacg

Câu trả lời:


3

CJam ( 39 38 byte)

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

Bản demo trực tuyến

Điều này tuân theo dòng gợi ý tìm một thừa số nguyên tố ( mF) và sau đó tính toán các phân vùng của từng công suất và lấy sản phẩm của chúng.

Có hai trường hợp đặc biệt cho mF: nó yếu tố 0như 0^11như 1^1. Loại thứ hai không yêu cầu xử lý đặc biệt: có một nhóm Abelian cỡ 1 và một phân vùng 1. Tuy nhiên, số 0 không yêu cầu trường hợp đặc biệt.

Việc đếm phân vùng sử dụng một lần lặp lại cho A008284(n, k), số lượng phân vùng nthành kcác phần. Trong OEIS, nó được đưa ra là

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

nhưng tôi nghĩ rằng nó hữu ích hơn để suy nghĩ số tiền như nhau, từ 1đến min(k, n-k).

Mổ xẻ

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 byte

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

Sử dụng hệ số dựng sẵn của CJam mFvà một cổng được ghi nhớ của hàm số phân vùng Python này:

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

hoặc vô lương tâm:

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)

Giống như câu trả lời của @ RetoKoradi, trường hợp cuối cùng mất khoảng 17 giây cho trình thông dịch ngoại tuyến vì đó là khoảng thời gian để CJam tính đến con số. Do đó tôi đã bỏ nó ra khỏi bộ thử nghiệm trực tuyến này .

Giải thích đầy đủ

[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

Toán học, 96 94 88 byte

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

Tôi không rành về Mathicala, nhưng tôi nghĩ tôi sẽ thử. Cảm ơn @ MartinBüttner cho -6 byte.

Điều này sử dụng công thức hàm tạo cho các phân vùng số nguyên.


3

CJam, 58 byte

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

Dùng thử trực tuyến

Ví dụ thử nghiệm cuối cùng mất mãi mãi (hoặc ít nhất là lâu hơn tôi sẵn sàng chờ đợi) trong trình thông dịch trực tuyến, nhưng kết thúc sau 17 giây với phiên bản ngoại tuyến của CJam trên máy tính xách tay của tôi. Tất cả các ví dụ kiểm tra khác là khá nhiều ngay lập tức.

Điều này sử dụng mFtoán tử CJam , cung cấp hệ số nguyên tố với số mũ. Kết quả là sản phẩm của phân vùng được tính cho mỗi số mũ.

Phần chính của mã là tính toán số lượng phân vùng. Tôi đã triển khai thuật toán đệ quy trên trang wikipedia , sử dụngj toán tử hỗ trợ đệ quy với ghi nhớ.

Giải trình:

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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.