找到所有可能的半正定整数,其加权和等于某个整数
Find all possible positive semi definite integers whose weighted sum is equal certain integer
我在使用 Fortran 90 代码时遇到问题。所以,我有 n+1
个半正定整数 k1
、k2
、k3
、...、kn
和 n
。现在对于给定的 n
,我需要找到 k1
、k2
、k3
、...、kn
的所有可能组合,使得 k1+2*k2+3*k3+...+n*kn = n
.人们可能会想到使用 n 级嵌套循环,每个 for ki
从 0
运行到 n
但实际上我会将这段代码放在子例程中 n
(即 k
的数量)将作为该子程序的输入。因此,如果我要使用嵌套循环,那么嵌套级别的数量应该是自动化的,我认为这很难(如果不是不可能)用 Fortran 实现。有没有更好的方法来解决这个问题?
如果n
相当小(比如说,5),我认为编写多维循环以获得满足的所需k向量(k1,k2,...,kn)会更简单k1 + k2*2 + ... + kn*n = n。否则,它可能是使用递归的一种选择。示例代码可能如下所示(注意我们需要 recursive
关键字):
module recur_mod
implicit none
integer, parameter :: nvecmax = 1000
contains
subroutine recur_main( n, kveclist, nvec )
integer, intent(in) :: n
integer, allocatable, intent(out) :: kveclist(:,:) !! list of k-vectors
integer, intent(out) :: nvec !! number of k-vectors
integer kvec( n ), ind
allocate( kveclist( n, nvecmax ) )
kveclist(:,:) = 0
nvec = 0
ind = 1
kvec(:) = 0
call recur_sub( n, ind, kvec, kveclist, nvec ) !! now entering recursion...
endsubroutine
recursive subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k, ksum, t, ind_next
do k = 0, n
kvec( ind ) = k
ksum = sum( [( kvec( t ) * t, t = 1, ind )] ) !! k1 + k2*2 + ... + ki*i
if ( ksum > n ) cycle !! early rejection
if ( ind < n ) then
ind_next = ind + 1
call recur_sub( n, ind_next, kvec, kveclist, nvec ) !! go to the next index
endif
if ( ind == n .and. ksum == n ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:) !! save k-vectors
endif
enddo
endsubroutine
end
program main
use recur_mod
implicit none
integer, allocatable :: kveclist(:,:)
integer :: n, nvec, ivec
do n = 1, 4
call recur_main( n, kveclist, nvec )
print *
print *, "For n = ", n
do ivec = 1, nvec
print *, "kvec = ", kveclist( :, ivec )
enddo
enddo
end
给出(使用 gfortran 7.1)
For n = 1
kvec = 1
For n = 2
kvec = 0 1
kvec = 2 0
For n = 3
kvec = 0 0 1
kvec = 1 1 0
kvec = 3 0 0
For n = 4
kvec = 0 0 0 1
kvec = 0 2 0 0
kvec = 1 0 1 0
kvec = 2 1 0 0
kvec = 4 0 0 0
这里,我们可以看出,例如kvec = [k1,k2,k3,k4] = [2,1,0,0]
for n=4 满足k1 + k2*2 + k3*3 + k4*4 = 2 + 1*2 + 0 + 0 = 4
。使用这些 k 向量,我们可以评估 f(g(x)) 的 n 阶导数(如 OP 所述,在 page 之后)。
要看递归是如何工作的,插入很多通常很有用
print
语句并监视变量如何变化。例如,代码的 "verbose" 版本可能如下所示(此处,为简单起见,我删除了早期拒绝的内容):
recursive subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k, ksum, t, ind_next
print *, "Top of recur_sub: ind = ", ind
do k = 0, n
kvec( ind ) = k
print *, "ind = ", ind, " k = ", k, "kvec = ", kvec
if ( ind < n ) then
ind_next = ind + 1
print *, " > now going to the next level"
call recur_sub( n, ind_next, kvec, kveclist, nvec )
print *, " > returned to the current level"
endif
if ( ind == n ) then
ksum = sum( [( kvec( t ) * t, t = 1, n )] )
if ( ksum == n ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:)
endif
endif
enddo
print *, "Exiting recur_sub"
endsubroutine
n = 2
:
Top of recur_sub: ind = 1
ind = 1 k = 0 kvec = 0 0
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 0 0
ind = 2 k = 1 kvec = 0 1
ind = 2 k = 2 kvec = 0 2
Exiting recur_sub
> returned to the current level
ind = 1 k = 1 kvec = 1 2
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 1 0
ind = 2 k = 1 kvec = 1 1
ind = 2 k = 2 kvec = 1 2
Exiting recur_sub
> returned to the current level
ind = 1 k = 2 kvec = 2 2
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 2 0
ind = 2 k = 1 kvec = 2 1
ind = 2 k = 2 kvec = 2 2
Exiting recur_sub
> returned to the current level
Exiting recur_sub
For n = 2
kvec = 0 1
kvec = 2 0
请注意,数组 kvec
和 kveclist
的值始终在递归调用的进入和退出时保留。特别是,我们正在为每个维度覆盖 kvec
的元素以获得可能模式的完整列表(因此本质上等同于多维循环)。我们还注意到 kvec
的值仅在最终递归级别(即 ind = n
)才有意义。
获得工作的另一种方法是将递归调用重写为特定 n
的等效非递归调用。例如,n = 2
的情况可以改写如下。这不依赖于递归,而是执行与上述代码相同的操作(对于 n = 2
)。如果我们想象将 recur_sub2
内联到 recur_sub
,很明显这些例程等效于 k1
和 k2
.
上的二维循环
!! routine specific for n = 2
subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k1
!! now ind == 1
do k1 = 0, n
kvec( ind ) = k1
call recur_sub2( n, ind + 1, kvec, kveclist, nvec ) !! go to next index
enddo
endsubroutine
!! routine specific for n = 2
subroutine recur_sub2( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k2, ksum, t
!! now ind == n == 2
do k2 = 0, n
kvec( ind ) = k2
ksum = sum( [( kvec( t ) * t, t = 1, n )] )
if ( ksum == 2 ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:) !! save k-vectors
endif
enddo
endsubroutine
附录
以下是 f(g(x)) 的 n 阶导数的 "pretty print" 例程(在 Julia 中)(仅供娱乐)。如有需要,请用Fortran编写相应例程(但请注意大n!)
function recur_main( n )
kvec = zeros( Int, n ) # [k1,k2,...,kn] (work vector)
kveclist = Vector{Int}[] # list of k-vectors (output)
recur_sub( n, 1, kvec, kveclist ) # now entering recursion over {ki}...
return kveclist
end
function recur_sub( n, i, kvec, kveclist )
for ki = 0 : n
kvec[ i ] = ki
ksum = sum( kvec[ t ] * t for t = 1:i ) # k1 + k2*2 + ... + ki*i
ksum > n && continue # early rejection
if i < n
recur_sub( n, i + 1, kvec, kveclist ) # go to the next index
end
if i == n && ksum == n
push!( kveclist, copy( kvec ) ) # save k-vectors
end
end
end
function showderiv( n )
kveclist = recur_main( n )
println()
println( "(f(g))_$(n) = " )
fact( k ) = factorial( big(k) )
for (term, kvec) in enumerate( kveclist )
fac1 = div( fact( n ), prod( fact( kvec[ i ] ) for i = 1:n ) )
fac2 = prod( fact( i )^kvec[ i ] for i = 1:n )
coeff = div( fac1, fac2 )
term == 1 ? print( " " ) : print( " + " )
coeff == 1 ? print( " " ^ 15 ) : @printf( "%15i", coeff )
print( " (f$( sum( kvec ) ))" )
for i = 1 : length( kvec )
ki = kvec[ i ]
if ki > 0
print( "(g$( i ))" )
ki > 1 && print( "^$( ki )" )
end
end
println()
end
end
#--- test ---
if false
for n = 1 : 4
kveclist = recur_main( n )
println( "\nFor n = ", n )
for kvec in kveclist
println( "kvec = ", kvec )
end
end
end
showderiv( 1 )
showderiv( 2 )
showderiv( 3 )
showderiv( 4 )
showderiv( 5 )
showderiv( 8 )
showderiv( 10 )
结果(其中fm
和gm
分别表示f
和g
的第m阶导数):
(f(g))_1 =
(f1)(g1)
(f(g))_2 =
(f1)(g2)
+ (f2)(g1)^2
(f(g))_3 =
(f1)(g3)
+ 3 (f2)(g1)(g2)
+ (f3)(g1)^3
(f(g))_4 =
(f1)(g4)
+ 3 (f2)(g2)^2
+ 4 (f2)(g1)(g3)
+ 6 (f3)(g1)^2(g2)
+ (f4)(g1)^4
(f(g))_5 =
(f1)(g5)
+ 10 (f2)(g2)(g3)
+ 5 (f2)(g1)(g4)
+ 15 (f3)(g1)(g2)^2
+ 10 (f3)(g1)^2(g3)
+ 10 (f4)(g1)^3(g2)
+ (f5)(g1)^5
(f(g))_8 =
(f1)(g8)
+ 35 (f2)(g4)^2
+ 56 (f2)(g3)(g5)
+ 28 (f2)(g2)(g6)
+ 280 (f3)(g2)(g3)^2
+ 210 (f3)(g2)^2(g4)
+ 105 (f4)(g2)^4
+ 8 (f2)(g1)(g7)
+ 280 (f3)(g1)(g3)(g4)
+ 168 (f3)(g1)(g2)(g5)
+ 840 (f4)(g1)(g2)^2(g3)
+ 28 (f3)(g1)^2(g6)
+ 280 (f4)(g1)^2(g3)^2
+ 420 (f4)(g1)^2(g2)(g4)
+ 420 (f5)(g1)^2(g2)^3
+ 56 (f4)(g1)^3(g5)
+ 560 (f5)(g1)^3(g2)(g3)
+ 70 (f5)(g1)^4(g4)
+ 210 (f6)(g1)^4(g2)^2
+ 56 (f6)(g1)^5(g3)
+ 28 (f7)(g1)^6(g2)
+ (f8)(g1)^8
(f(g))_10 =
(f1)(g10)
+ 126 (f2)(g5)^2
+ 210 (f2)(g4)(g6)
+ 120 (f2)(g3)(g7)
+ 2100 (f3)(g3)^2(g4)
+ 45 (f2)(g2)(g8)
+ 1575 (f3)(g2)(g4)^2
+ 2520 (f3)(g2)(g3)(g5)
+ 630 (f3)(g2)^2(g6)
+ 6300 (f4)(g2)^2(g3)^2
+ 3150 (f4)(g2)^3(g4)
+ 945 (f5)(g2)^5
+ 10 (f2)(g1)(g9)
+ 1260 (f3)(g1)(g4)(g5)
+ 840 (f3)(g1)(g3)(g6)
+ 2800 (f4)(g1)(g3)^3
+ 360 (f3)(g1)(g2)(g7)
+ 12600 (f4)(g1)(g2)(g3)(g4)
+ 3780 (f4)(g1)(g2)^2(g5)
+ 12600 (f5)(g1)(g2)^3(g3)
+ 45 (f3)(g1)^2(g8)
+ 1575 (f4)(g1)^2(g4)^2
+ 2520 (f4)(g1)^2(g3)(g5)
+ 1260 (f4)(g1)^2(g2)(g6)
+ 12600 (f5)(g1)^2(g2)(g3)^2
+ 9450 (f5)(g1)^2(g2)^2(g4)
+ 4725 (f6)(g1)^2(g2)^4
+ 120 (f4)(g1)^3(g7)
+ 4200 (f5)(g1)^3(g3)(g4)
+ 2520 (f5)(g1)^3(g2)(g5)
+ 12600 (f6)(g1)^3(g2)^2(g3)
+ 210 (f5)(g1)^4(g6)
+ 2100 (f6)(g1)^4(g3)^2
+ 3150 (f6)(g1)^4(g2)(g4)
+ 3150 (f7)(g1)^4(g2)^3
+ 252 (f6)(g1)^5(g5)
+ 2520 (f7)(g1)^5(g2)(g3)
+ 210 (f7)(g1)^6(g4)
+ 630 (f8)(g1)^6(g2)^2
+ 120 (f8)(g1)^7(g3)
+ 45 (f9)(g1)^8(g2)
+ (f10)(g1)^10
我在使用 Fortran 90 代码时遇到问题。所以,我有 n+1
个半正定整数 k1
、k2
、k3
、...、kn
和 n
。现在对于给定的 n
,我需要找到 k1
、k2
、k3
、...、kn
的所有可能组合,使得 k1+2*k2+3*k3+...+n*kn = n
.人们可能会想到使用 n 级嵌套循环,每个 for ki
从 0
运行到 n
但实际上我会将这段代码放在子例程中 n
(即 k
的数量)将作为该子程序的输入。因此,如果我要使用嵌套循环,那么嵌套级别的数量应该是自动化的,我认为这很难(如果不是不可能)用 Fortran 实现。有没有更好的方法来解决这个问题?
如果n
相当小(比如说,5),我认为编写多维循环以获得满足的所需k向量(k1,k2,...,kn)会更简单k1 + k2*2 + ... + kn*n = n。否则,它可能是使用递归的一种选择。示例代码可能如下所示(注意我们需要 recursive
关键字):
module recur_mod
implicit none
integer, parameter :: nvecmax = 1000
contains
subroutine recur_main( n, kveclist, nvec )
integer, intent(in) :: n
integer, allocatable, intent(out) :: kveclist(:,:) !! list of k-vectors
integer, intent(out) :: nvec !! number of k-vectors
integer kvec( n ), ind
allocate( kveclist( n, nvecmax ) )
kveclist(:,:) = 0
nvec = 0
ind = 1
kvec(:) = 0
call recur_sub( n, ind, kvec, kveclist, nvec ) !! now entering recursion...
endsubroutine
recursive subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k, ksum, t, ind_next
do k = 0, n
kvec( ind ) = k
ksum = sum( [( kvec( t ) * t, t = 1, ind )] ) !! k1 + k2*2 + ... + ki*i
if ( ksum > n ) cycle !! early rejection
if ( ind < n ) then
ind_next = ind + 1
call recur_sub( n, ind_next, kvec, kveclist, nvec ) !! go to the next index
endif
if ( ind == n .and. ksum == n ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:) !! save k-vectors
endif
enddo
endsubroutine
end
program main
use recur_mod
implicit none
integer, allocatable :: kveclist(:,:)
integer :: n, nvec, ivec
do n = 1, 4
call recur_main( n, kveclist, nvec )
print *
print *, "For n = ", n
do ivec = 1, nvec
print *, "kvec = ", kveclist( :, ivec )
enddo
enddo
end
给出(使用 gfortran 7.1)
For n = 1
kvec = 1
For n = 2
kvec = 0 1
kvec = 2 0
For n = 3
kvec = 0 0 1
kvec = 1 1 0
kvec = 3 0 0
For n = 4
kvec = 0 0 0 1
kvec = 0 2 0 0
kvec = 1 0 1 0
kvec = 2 1 0 0
kvec = 4 0 0 0
这里,我们可以看出,例如kvec = [k1,k2,k3,k4] = [2,1,0,0]
for n=4 满足k1 + k2*2 + k3*3 + k4*4 = 2 + 1*2 + 0 + 0 = 4
。使用这些 k 向量,我们可以评估 f(g(x)) 的 n 阶导数(如 OP 所述,在 page 之后)。
要看递归是如何工作的,插入很多通常很有用
print
语句并监视变量如何变化。例如,代码的 "verbose" 版本可能如下所示(此处,为简单起见,我删除了早期拒绝的内容):
recursive subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k, ksum, t, ind_next
print *, "Top of recur_sub: ind = ", ind
do k = 0, n
kvec( ind ) = k
print *, "ind = ", ind, " k = ", k, "kvec = ", kvec
if ( ind < n ) then
ind_next = ind + 1
print *, " > now going to the next level"
call recur_sub( n, ind_next, kvec, kveclist, nvec )
print *, " > returned to the current level"
endif
if ( ind == n ) then
ksum = sum( [( kvec( t ) * t, t = 1, n )] )
if ( ksum == n ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:)
endif
endif
enddo
print *, "Exiting recur_sub"
endsubroutine
n = 2
:
Top of recur_sub: ind = 1
ind = 1 k = 0 kvec = 0 0
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 0 0
ind = 2 k = 1 kvec = 0 1
ind = 2 k = 2 kvec = 0 2
Exiting recur_sub
> returned to the current level
ind = 1 k = 1 kvec = 1 2
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 1 0
ind = 2 k = 1 kvec = 1 1
ind = 2 k = 2 kvec = 1 2
Exiting recur_sub
> returned to the current level
ind = 1 k = 2 kvec = 2 2
> now going to the next level
Top of recur_sub: ind = 2
ind = 2 k = 0 kvec = 2 0
ind = 2 k = 1 kvec = 2 1
ind = 2 k = 2 kvec = 2 2
Exiting recur_sub
> returned to the current level
Exiting recur_sub
For n = 2
kvec = 0 1
kvec = 2 0
请注意,数组 kvec
和 kveclist
的值始终在递归调用的进入和退出时保留。特别是,我们正在为每个维度覆盖 kvec
的元素以获得可能模式的完整列表(因此本质上等同于多维循环)。我们还注意到 kvec
的值仅在最终递归级别(即 ind = n
)才有意义。
获得工作的另一种方法是将递归调用重写为特定 n
的等效非递归调用。例如,n = 2
的情况可以改写如下。这不依赖于递归,而是执行与上述代码相同的操作(对于 n = 2
)。如果我们想象将 recur_sub2
内联到 recur_sub
,很明显这些例程等效于 k1
和 k2
.
!! routine specific for n = 2
subroutine recur_sub( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k1
!! now ind == 1
do k1 = 0, n
kvec( ind ) = k1
call recur_sub2( n, ind + 1, kvec, kveclist, nvec ) !! go to next index
enddo
endsubroutine
!! routine specific for n = 2
subroutine recur_sub2( n, ind, kvec, kveclist, nvec )
integer, intent(in) :: n, ind
integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
integer k2, ksum, t
!! now ind == n == 2
do k2 = 0, n
kvec( ind ) = k2
ksum = sum( [( kvec( t ) * t, t = 1, n )] )
if ( ksum == 2 ) then
nvec = nvec + 1
if ( nvec > nvecmax ) stop "nvecmax too small"
kveclist( :, nvec ) = kvec(:) !! save k-vectors
endif
enddo
endsubroutine
附录
以下是 f(g(x)) 的 n 阶导数的 "pretty print" 例程(在 Julia 中)(仅供娱乐)。如有需要,请用Fortran编写相应例程(但请注意大n!)
function recur_main( n )
kvec = zeros( Int, n ) # [k1,k2,...,kn] (work vector)
kveclist = Vector{Int}[] # list of k-vectors (output)
recur_sub( n, 1, kvec, kveclist ) # now entering recursion over {ki}...
return kveclist
end
function recur_sub( n, i, kvec, kveclist )
for ki = 0 : n
kvec[ i ] = ki
ksum = sum( kvec[ t ] * t for t = 1:i ) # k1 + k2*2 + ... + ki*i
ksum > n && continue # early rejection
if i < n
recur_sub( n, i + 1, kvec, kveclist ) # go to the next index
end
if i == n && ksum == n
push!( kveclist, copy( kvec ) ) # save k-vectors
end
end
end
function showderiv( n )
kveclist = recur_main( n )
println()
println( "(f(g))_$(n) = " )
fact( k ) = factorial( big(k) )
for (term, kvec) in enumerate( kveclist )
fac1 = div( fact( n ), prod( fact( kvec[ i ] ) for i = 1:n ) )
fac2 = prod( fact( i )^kvec[ i ] for i = 1:n )
coeff = div( fac1, fac2 )
term == 1 ? print( " " ) : print( " + " )
coeff == 1 ? print( " " ^ 15 ) : @printf( "%15i", coeff )
print( " (f$( sum( kvec ) ))" )
for i = 1 : length( kvec )
ki = kvec[ i ]
if ki > 0
print( "(g$( i ))" )
ki > 1 && print( "^$( ki )" )
end
end
println()
end
end
#--- test ---
if false
for n = 1 : 4
kveclist = recur_main( n )
println( "\nFor n = ", n )
for kvec in kveclist
println( "kvec = ", kvec )
end
end
end
showderiv( 1 )
showderiv( 2 )
showderiv( 3 )
showderiv( 4 )
showderiv( 5 )
showderiv( 8 )
showderiv( 10 )
结果(其中fm
和gm
分别表示f
和g
的第m阶导数):
(f(g))_1 =
(f1)(g1)
(f(g))_2 =
(f1)(g2)
+ (f2)(g1)^2
(f(g))_3 =
(f1)(g3)
+ 3 (f2)(g1)(g2)
+ (f3)(g1)^3
(f(g))_4 =
(f1)(g4)
+ 3 (f2)(g2)^2
+ 4 (f2)(g1)(g3)
+ 6 (f3)(g1)^2(g2)
+ (f4)(g1)^4
(f(g))_5 =
(f1)(g5)
+ 10 (f2)(g2)(g3)
+ 5 (f2)(g1)(g4)
+ 15 (f3)(g1)(g2)^2
+ 10 (f3)(g1)^2(g3)
+ 10 (f4)(g1)^3(g2)
+ (f5)(g1)^5
(f(g))_8 =
(f1)(g8)
+ 35 (f2)(g4)^2
+ 56 (f2)(g3)(g5)
+ 28 (f2)(g2)(g6)
+ 280 (f3)(g2)(g3)^2
+ 210 (f3)(g2)^2(g4)
+ 105 (f4)(g2)^4
+ 8 (f2)(g1)(g7)
+ 280 (f3)(g1)(g3)(g4)
+ 168 (f3)(g1)(g2)(g5)
+ 840 (f4)(g1)(g2)^2(g3)
+ 28 (f3)(g1)^2(g6)
+ 280 (f4)(g1)^2(g3)^2
+ 420 (f4)(g1)^2(g2)(g4)
+ 420 (f5)(g1)^2(g2)^3
+ 56 (f4)(g1)^3(g5)
+ 560 (f5)(g1)^3(g2)(g3)
+ 70 (f5)(g1)^4(g4)
+ 210 (f6)(g1)^4(g2)^2
+ 56 (f6)(g1)^5(g3)
+ 28 (f7)(g1)^6(g2)
+ (f8)(g1)^8
(f(g))_10 =
(f1)(g10)
+ 126 (f2)(g5)^2
+ 210 (f2)(g4)(g6)
+ 120 (f2)(g3)(g7)
+ 2100 (f3)(g3)^2(g4)
+ 45 (f2)(g2)(g8)
+ 1575 (f3)(g2)(g4)^2
+ 2520 (f3)(g2)(g3)(g5)
+ 630 (f3)(g2)^2(g6)
+ 6300 (f4)(g2)^2(g3)^2
+ 3150 (f4)(g2)^3(g4)
+ 945 (f5)(g2)^5
+ 10 (f2)(g1)(g9)
+ 1260 (f3)(g1)(g4)(g5)
+ 840 (f3)(g1)(g3)(g6)
+ 2800 (f4)(g1)(g3)^3
+ 360 (f3)(g1)(g2)(g7)
+ 12600 (f4)(g1)(g2)(g3)(g4)
+ 3780 (f4)(g1)(g2)^2(g5)
+ 12600 (f5)(g1)(g2)^3(g3)
+ 45 (f3)(g1)^2(g8)
+ 1575 (f4)(g1)^2(g4)^2
+ 2520 (f4)(g1)^2(g3)(g5)
+ 1260 (f4)(g1)^2(g2)(g6)
+ 12600 (f5)(g1)^2(g2)(g3)^2
+ 9450 (f5)(g1)^2(g2)^2(g4)
+ 4725 (f6)(g1)^2(g2)^4
+ 120 (f4)(g1)^3(g7)
+ 4200 (f5)(g1)^3(g3)(g4)
+ 2520 (f5)(g1)^3(g2)(g5)
+ 12600 (f6)(g1)^3(g2)^2(g3)
+ 210 (f5)(g1)^4(g6)
+ 2100 (f6)(g1)^4(g3)^2
+ 3150 (f6)(g1)^4(g2)(g4)
+ 3150 (f7)(g1)^4(g2)^3
+ 252 (f6)(g1)^5(g5)
+ 2520 (f7)(g1)^5(g2)(g3)
+ 210 (f7)(g1)^6(g4)
+ 630 (f8)(g1)^6(g2)^2
+ 120 (f8)(g1)^7(g3)
+ 45 (f9)(g1)^8(g2)
+ (f10)(g1)^10