如何将两个生成级数相乘?

How do you multiply two generating series?

如果这更适合 MathOverflow,请原谅我,但我的问题可能太简单了,无法放在那里。

我正在阅读 S.K Lando 的 生成函数讲座 ,其中给出了两个生成函数的乘积的定义 AB:

A(s)*B(s) = a0*b0 + (a0*b1 + a1*b0)*s + (a0*b2 + a1*b1 + a2*b0)*s^2 ...

我知道 s 只是正式的。但是——我知道这对我来说很迟钝——我不明白组合系数的模式应该如何继续。如果有人可以将定义扩展到一两个术语,那可能会对我有很大帮助。非常感谢!

对于奖励积分,Haskell 中用于将两个级数相乘的算法(表示为系数列表)也将非常受欢迎 - 但我只需要理解上述定义就足够了。

请注意,系数指数的总和在每一项中都是常数。例如 a0*b0 -> 0+0=0,而 a0*b1 -> 0+1=1a1*b0 -> 1+0=1.

回想一下 story of young Gauss,他发现通过将连续数字列表与其倒数相加,我们得到一个 常数列表 。同样的技巧也适用于此。我们只取前 k 个 a_ib_i 系数,反转 b_i 系数列表,然后取列表的分量乘积。

这里有一些 Haskell 代码,用于为 i>=0 生成 s^i 的系数,给定 i 以及 as=[a0,a1,...] 和 [=22= 的列表]:

genCoeff :: [Double] -> [Double] -> Int -> Double
genCoeff as bs i = sum $ zipWith (*) (take (i+1) as) (reverse (take (i+1) bs))

要生成所有系数,我们只需将部分应用的函数 genCoeff as bs 映射到列表 [0,1,...],即

genAllCeoffs :: [Double] -> [Double] -> [Double]
genAllCoeffs as bs = map (genCoeff as bs) [0..]

这是一个不使用 reverse 的解决方案:

add [] bs = bs
add as [] = as
add (a:as) (b:bs) = (a+b) : add as bs

mult :: [Int] -> [Int] -> [Int]
mult [] bs = []   -- note: [] = 0
mult as [] = []
mult (a:as) (b:bs) = (a*b) : add (add (map (*a) bs) (map (*b) as)) (0:mult as bs)

test1 = do
  let as = [1,2,3]
      bs = [4,5]
  putStrLn $ "as      = " ++ show as
  putStrLn $ "bs      = " ++ show bs
  putStrLn $ "as * bs = " ++ show (mult as bs)

输出:

as      = [1,2,3]
bs      = [4,5]
as * bs = [4,13,22,15]

它源自以下身份:

(a0+a1*x) * (b0 + b1*x) = a0*b0 + a0*b1*x + b0*a1*x + a1*b1*x^2

对应关系是:

a0*b0          <-> a*b
a0*b1*x        <-> map (*a) bs
b0*a1*x        <-> map (*b) as
a1*b1*x^2      <-> (0:mult as bs)