Belirli bir büyüklükteki Abelian gruplarını sayma


14

Arka fon

Son kez, önemsiz bir sorun olan belirli bir boyuttaki grupları saydık .

Bu sefer sadece Abel gruplarını , yani değişmeli operasyonu olan grupları sayacağız . Biçimsel olarak, bir grup (G *) değişmeli ise x * y = Y * X tüm için x, y olarak G .

Sorun bu şekilde çok daha basit hale geliyor, bu yüzden onları verimli bir şekilde sayacağız.

Görev

Negatif olmayan bir tamsayıyı n girdi olarak kabul eden ve izomorfik olmayan Abelian sipariş n'nin sayısını basan veya döndüren bir program veya işlev yazın .

A (n) ile ifade edeceğimiz grup sayısını hesaplamanın bir yolu aşağıdakileri gözlemlemektir:

  • A (0) = 0

  • Eğer p bir asal, A (p k ) tamsayı bölümlerin sayısı eşittir k . ( krş . OEIS A000041 )

  • Eğer , n = mk ve m ve k eş asal, A (n) = ve A (m) bir (k) .

Bunu veya A (n) 'yi hesaplamak için başka herhangi bir yöntemi kullanabilirsiniz .

Test senaryoları

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'den alınmıştır )

Ek kurallar

  • Yeterli zaman, RAM ve girişi tutabilen bir kayıt boyutu verildiğinde, kodunuz keyfi olarak büyük tamsayılar için çalışmalıdır (teoride).

  • Kodunuz tüm tamsayılar arasındaki için çalışmalıdır 0 ve 2 63 - 1 benim makinede 10 dakika (Intel i7-3770, 16 GiB RAM, Fedora 21) altında ve bitiş.

    Lütfen yanıtınızı göndermeden önce kodunuzu son üç test vakası için zamanladığınızdan emin olun.

  • Mathematica'nınki gibi bu görevi önemsizleştiren yerleşik FiniteAbelianGroupCountyapılara izin verilmez.

  • Bir sayının tamsayı bölümlerini veya bir listenin bölümlerini döndüren veya sayan yerleşik öğelere izin verilmez.

  • Standart kuralları geçerlidir.


Pyth'in asal çarpanlarına ayırma sistemi bu zorluk için çok yavaş - bunu düzeltmem gerekiyor.
isaacg

Yanıtlar:


3

CJam ( 39 38 bayt)

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

Çevrimiçi demo

Bu, asal çarpanlara mFayırma ( ) bulma ve ardından her bir gücün bölümlerini hesaplama ve ürünlerini alma konusunda önerilen çizgiyi izler .

İçin iki özel durum vardır mF: o faktörler 0olarak 0^1ve 1sıra 1^1. İkincisi özel tedavi gerektirmez: 1 numaralı bir Abelian grubu ve 1'lik bir bölüm vardır. Ancak, sıfır özel bir durum gerektirir.

Bölüm sayma için bir tekrarını kullanır A008284(n, k), bir bölüm sayısını niçine kparçaları. OEIS'te şu şekilde verilir:

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

ama bunun kadar değişen olarak toplamına düşünmek daha yararlı olduğunu düşünüyorum 1için min(k, n-k).

teşrih

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 bayt

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

CJam'ın yerleşik mFçarpanlarına ayırma işlemini ve bu Python bölüm numarası işlevinin kaydedilmiş bir bağlantı noktasını kullanır :

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

veya çözülmemiş:

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'nin cevabı gibi, son dava çevrimdışı tercümanda yaklaşık 17 saniye sürer, çünkü CJam'ın sayıyı çarpanlarına ayırması ne kadar sürer. Bu yüzden bu çevrimiçi test paketinin dışında bıraktım .

Tam açıklama

[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

Mathematica, 96 94 88 bayt

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

Mathematica konusunda yetkin değilim, ama denemeyi düşündüm. -6 baytlık @ MartinBüttner'a teşekkürler.

Bu, tamsayı bölümler için oluşturma işlevi formülünü kullanır.


3

CJam, 58 bayt

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

Çevrimiçi deneyin

En son test örneği çevrimiçi yorumlayıcıda sonsuza kadar (veya beklemek istediğimden daha uzun) sürüyor, ancak dizüstü bilgisayarımdaki CJam'ın çevrimdışı sürümü ile 17 saniye içinde bitiyor. Diğer tüm test örnekleri hemen hemen anlıktır.

Bu, üslerle mFbirincil çarpanlara ayırma sağlayan CJam operatörünü kullanır . Sonuç, her bir üs için bölüm sayımının ürünüdür.

Kodun ana bölümü, bölüm sayılarını hesaplamaktır. Özyinelemeli algoritmayı wikipedia sayfasında , jhatırlatma ile özyinelemeyi destekleyen operatörü kullanarak uyguladım.

Açıklama:

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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.