Hardy & Ramanujan と Rademacher によって、分割数 p(n) を漸化式を使わずに、直接計算できる式が与えられています。これを使って分割数を求めてみたいと思います。なお式の証明には、かなり高度な知識が要求されるようなので、結果だけ頂戴します。
分割数を直接計算できる式は、整数の分割という素朴なものとは思えないような複雑な形をしているので、数学科の連中が我等純真な素人を驚かすのによく持ち出してきます。ところが、計算して確かめてみることが可能な形で、はっきりと与えられることが少なく、しかも無限級数になっているので、ありがたみも少なめです。
G.E.Andrews の The Theory of Partitions に計算例が載っていますが、式が複雑で計算する気が起きませんでした。
J.Remmel & A.Mendes の Counting with Symmetric Functions に計算してみる気が起きる程度に簡単にまとめられた式が載っていたので、ここでは実際に数値を入れて計算してみます。
この式は、G.E.Andrews の与える式と微妙に違っていますが、別途計算して見たところ、結果は同じになるようなので、24乗根の取り方の違いなのかなんなのか(追記:デデキント和の別表現のようです。)、どっちでもよさそうな感じです。(一度計算できると、 Andrews の式も微修正で計算できました。)
ソース・プログラム
本来は、変数 k に関する和は無限和ですが、10 までで止めておきます。これでも大体十分です。k=100 まで和をとった場合と比較して、n ~ 1000 までで、結果に 0.3 程度の誤差が出ますが、四捨五入すると関係ありません。
module m_part
implicit none
integer , parameter :: kd = kind(1.0q0)
real(kd), parameter :: pi = 4 * atan(1.0_kd)
contains
complex(kd) pure function cpartition(n)
integer, intent(in) :: n
integer, parameter :: kmax = 10
real(kd) :: f, s, t
complex(kd) :: c
integer :: j, m, k
cpartition = (0.0_kd, 0.0_kd)
do k = 1, kmax
f = sqrt(k / 2.0_kd) / pi
c = (0.0_kd, 0.0_kd)
do m = 1, k
if (igcd(m, k) == 1) then
s = -real(2 * n * m, kd) / k
do j = 1, k - 1
t = real(m * j, kd) / k
s = s + real(j, kd) / k * (t - floor(t) - 0.5_kd)
end do
c = c + exp(cmplx(0.0_kd, pi * s, kind = kd))
end if
end do
cpartition = cpartition + f * c * da(k, n)
end do
end function cpartition
integer pure function igcd(ia, ib)
integer, intent(in) :: ia, ib
integer :: m(2)
m = [ia, ib]
do
m = [m(2), mod(m(1), m(2))]
if (m(2) == 0) exit
end do
igcd = m(1)
end function igcd
real(kd) pure function da(k, n)
integer, intent(in) :: k, n
real(kd) :: xs, f
xs = sqrt( real(n, kd) - 1.0_kd / 24.0_kd )
f = pi / k * sqrt(2.0_kd / 3.0_kd)
da = ( f * cosh(f * xs) - sinh(f * xs) / xs ) / (2 * xs * xs)
end function da
end module m_part
program Pn
use m_part
implicit none
integer :: i
complex(kind = kd) :: z
do i = 1, 1000
print '(i7, f45.3, i30)', i, real( cpartition(i), kd ), nint(real( cpartition(i), kd ), kind = 8)
end do
end program Pn
実行結果
1 1.006 1
2 2.004 2
3 3.002 3
4 4.996 5
5 6.997 7
6 10.989 11
7 15.000 15
8 21.994 22
9 30.004 30
10 42.008 42
400 近傍で 8 バイト整数の範囲を越えます。
400 6727090051741041925.961 6727090051741041926
401 7154640222653942320.999 7154640222653942321
402 7608802843339879269.005 7608802843339879269
403 8091200276484465580.978 8091200276484465581
404 8603551759348655060.036 8603551759348655060
405 9147679068859117602.063 9147679068859117602
406 9725512513742021729.066 -9223372036854775808
407 10339097267123947240.969 -9223372036854775808
408 10990600063775926994.010 -9223372036854775808
409 11682316277192317779.980 -9223372036854775808
990 16183531619906475296861224625026.766 -9223372036854775808
991 16839773100833956878604913215476.879 -9223372036854775808
992 17522282609145324707635966077021.986 -9223372036854775808
993 18232098083140097717852712346115.225 -9223372036854775808
994 18970297947002453464660671155989.793 -9223372036854775808
995 19738002669751617842096992232436.119 -9223372036854775808
996 20536376383452971700767593594020.746 -9223372036854775808
997 21366628562913781584556907794729.258 -9223372036854775808
998 22230015769169865076825741905554.660 -9223372036854775808
999 23127843459154899464880444632250.039 -9223372036854775808
1000 24061467864032622473692149727991.395 -9223372036854775808
続行するには何かキーを押してください . . .
漸化式によって求めた p(1000) の値は p(1000)=24061467864032622473692149727991 となっていて、四捨五入後の結果と一致します。