五边形数定理

五边形数定理

五边形数

在这里插入图片描述

定义如上图,通项公式为
p n = 3 n 2 − n 2 p_n=\frac{3n^2-n}{2} pn=23n2n

广义五边形数

广义五边形数的公式和五边形数相同,只是 n n n 可以为负数和零, n n n 依序为 0 , 1 , − 1 , 2 , − 2 , 3 , − 3 , 4 ⋯ 0, 1, -1, 2, -2, 3, -3, 4\cdots 0,1,1,2,2,3,3,4 广义五边形数也可以用下式表示:
p n = 2 n 2 ± n 2 p_n=\frac{2n^2\pm n}{2} pn=22n2±n
n n n 依序为 0 , 1 , 2 , 3 , 4 ⋯ 0, 1, 2, 3, 4\cdots 0,1,2,3,4

五边形数定理

欧拉函数的展开式如下:
∏ i = 1 ∞ ( 1 − x i ) = ∑ i = − ∞ ∞ ( − 1 ) i x i ( 3 i − 1 ) 2 = 1 + ∑ i = 1 ∞ ( − 1 ) i x i ( 3 i ± 1 ) 2 \prod_{i=1}^{\infty}(1-x^i)=\sum_{i=-\infty}^{\infty}(-1)^ix^{\frac{i(3i-1)}{2}}=1+\sum_{i=1}^\infty (-1)^ix^{\frac{i(3i\pm1)}{2}} i=1(1xi)=i=(1)ix2i(3i1)=1+i=1(1)ix2i(3i±1)
证明略。

欧拉函数展开后,有些次方项被消去,只留下次方项为 1 , 2 , 5 , 7 , 12 , ⋯ 1, 2, 5, 7, 12,\cdots 1,2,5,7,12, 的项次,留下来的次方恰为广义五边形数。

整数划分问题

使用正整数相加组合成n的方案数,比如 4 4 4 有以下几种: 1 + 1 + 1 + 1 , 2 + 2 , 4 , 1 + 3 , 1 + 1 + 2 1+1+1+1, 2+2,4,1+3,1+1+2 1+1+1+1,2+2,4,1+3,1+1+2

  • dp 做法

    d p [ i ] [ j ] dp[i][j] dp[i][j] 表示使用不大于 j j j 的正整数来组成 i i i 的方案数,则状态转移方程为:
    { d p [ i ] [ j ] = d p [ i − j ] [ j ] + d p [ i ] [ j − 1 ] i ≥ j d p [ i ] [ j ] = d p [ i ] [ i ] i < j \left\{\begin{matrix} dp[i][j]=dp[i-j][j]+dp[i][j-1]&&i\geq j\\ dp[i][j]=dp[i][i]&& i<j \end{matrix}\right. {dp[i][j]=dp[ij][j]+dp[i][j1]dp[i][j]=dp[i][i]iji<j

  • 生成函数+五边形数定理

    n n n 的拆分方案数为 p ( n ) p(n) p(n) ,则欧拉函数的倒数为分割函数的母函数 F ( x ) F(x) F(x) ,即
    F ( x ) = ∑ i = 0 ∞ p ( i ) x i = 1 ϕ ( x ) = ∏ i = 1 ∞ 1 1 − x i F(x)=\sum_{i=0}^\infty p(i)x^i=\frac{1}{\phi(x)}=\prod_{i=1}^\infty\frac{1}{1-x^i} F(x)=i=0p(i)xi=ϕ(x)1=i=11xi1
    证明:对于每一个数 i i i 考虑选 0 , 1 , 2 , 3 , ⋯ 0,1,2,3,\cdots 0,1,2,3, 次,则生成函数为
    g ( i ) = 1 + x i + x 2 i + ⋯ = 1 1 − x i g(i)=1+x^i+x^{2i}+\cdots=\frac{1}{1-x^i} g(i)=1+xi+x2i+=1xi1
    将每一个数的生成函数相乘,得:
    F ( x ) = ∏ i = 0 ∞ g ( i ) = 1 ϕ ( x ) F(x)=\prod_{i=0}^\infty g(i)=\frac{1}{\phi(x)} F(x)=i=0g(i)=ϕ(x)1
    得证。

    由于上述等式成立,考虑等式两边同乘以 ϕ ( x ) \phi(x) ϕ(x) ,得
    F ( x ) ϕ ( x ) = 1 F(x)\phi(x)=1 F(x)ϕ(x)=1
    根据五边形数定理展开得
    ∑ i = 0 ∞ p ( i ) x i ( 1 + ∑ j = 1 ∞ ( − 1 ) j x j ( 3 j ± 1 ) 2 ) = 1 \sum_{i=0}^\infty p(i)x^i(1+\sum_{j=1}^\infty (-1)^jx^{\frac{j(3j\pm1)}{2}})=1 i=0p(i)xi(1+j=1(1)jx2j(3j±1))=1
    由于等式右边不含 x x x ,因此等式左边展开后 x k x^k xk 的系数均为 0 0 0

    因此由五边形数定理展开后 x x x 的幂次为广义五边形数,通过固定展开式中 x x x 的幂次可以得出如下递推式:
    p ( n ) = p ( n − 1 ) + p ( n − 2 ) − p ( n − 5 ) − p ( n − 7 ) + ⋯ p(n)=p(n-1)+p(n-2)-p(n-5)-p(n-7)+\cdots p(n)=p(n1)+p(n2)p(n5)p(n7)+
    而上式中 n n n 减掉的数正是广义五边形数。

    由于五边形数的增长速度是 O ( n 2 ) O(n^2) O(n2) ,因此可以 O ( n ) O(\sqrt n) O(n ) 枚举五边形数暴力 dp ,总时间复杂度为 O ( n n ) O(n\sqrt n) O(nn )

例题:HDU4651 Partition

求解 p ( n ) p(n) p(n) ,方法如上。

const int N = 1e5 + 10, MOD = 1e9 + 7;

inline void add(int &x, int y) {
    x += y;
    if (x >= MOD) x -= MOD;
}

inline void sub(int &x, int y) {
    x -= y;
    if (x < 0) x += MOD;
}

int p[600], T, dp[N], n[N], mxn;

int main() {
    scanf("%d", &T);
    for (int i = 1; i <= T; i++)scanf("%d", &n[i]);
    mxn = *max_element(n + 1, n + 1 + T);
    for (int i = 1, j = 1;; i += 2, j++) {
        p[i] = (3 * j * j - j) >> 1;
        if (p[i] > mxn)break;
        p[i + 1] = (3 * j * j + j) >> 1;
        if (p[i + 1] > mxn)break;
    }
    dp[0] = 1;
    for (int i = 1; i <= mxn; i++)
        for (int j = 1; p[j] <= i; j++) {
            if ((j + 1) >> 1 & 1) add(dp[i], dp[i - p[j]]);
            else sub(dp[i], dp[i - p[j]]);
        }
    for (int i = 1; i <= T; i++)
        printf("%d\n", dp[n[i]]);
    return 0;
}

例题:HDU4658 Integer Partition

将一个正整数 n n n 划分为多个正整数的和的方案数,但每个数的使用次数小于 k k k 次。

不难得出生成函数为:
G ( x ) = ∏ i = 1 ∞ ∑ j = 0 k − 1 x i j G(x)=\prod_{i=1}^{\infty}\sum_{j=0}^{k-1}x^{ij} G(x)=i=1j=0k1xij
显然内部求和部分可以根据等比数列求和化简,得
G ( x ) = ∏ i = 1 ∞ 1 − x k i 1 − x i = ϕ ( x k ) ϕ ( x ) G(x)=\prod_{i=1}^{\infty}\frac{1-x^{ki}}{1-x^i}=\frac{\phi(x^k)}{\phi(x)} G(x)=i=11xi1xki=ϕ(x)ϕ(xk)
此时如果按两边同乘以 ϕ ( x ) \phi(x) ϕ(x) ,然后暴力展开找递推式的方法做就会发现等式右边 ϕ ( x k ) \phi(x^k) ϕ(xk) 中的 x i x^i xi 系数不固定,求解相当麻烦,因此考虑转化到已求解的问题上去。

观察发现:
G ( x ) = ϕ ( x k ) F ( x ) = ( 1 + ∑ i = 1 ∞ ( − 1 ) i x k i ( 3 i ± 1 ) 2 ) ( ∑ i = 0 ∞ p ( i ) x i ) G(x)=\phi(x^k)F(x)\\ =(1+\sum_{i=1}^\infty (-1)^ix^{k\frac{i(3i\pm1)}{2}})(\sum_{i=0}^\infty p(i)x^i) G(x)=ϕ(xk)F(x)=(1+i=1(1)ixk2i(3i±1))(i=0p(i)xi)

G ( x ) = ∑ i = 0 ∞ p ′ ( i ) x i G(x)=\sum_{i=0}^\infty p'(i)x^i G(x)=i=0p(i)xi

p ′ ( n ) = p ( n ) − p ( n − k ) − p ( n − 2 k ) + p ( n − 5 k ) + ⋯ p'(n)=p(n)-p(n-k)-p(n-2k)+p(n-5k)+\cdots p(n)=p(n)p(nk)p(n2k)+p(n5k)+
其中 p ( 1 ∼ n ) p(1\sim n) p(1n) 可以 O ( n n ) O(n\sqrt n) O(nn ) 预处理,之后每个 p ′ ( n ) p'(n) p(n) 均可以 O ( n ) O(\sqrt n) O(n ) 查询。时间复杂度为 O ( ( n + T ) n ) O((n+T)\sqrt n) O((n+T)n )

const int N = 1e5 + 10, MOD = 1e9 + 7;

inline void add(int &x, int y) {
    x += y;
    if (x >= MOD) x -= MOD;
}

inline void sub(int &x, int y) {
    x -= y;
    if (x < 0) x += MOD;
}

int p[600], T, dp[N], n[N], k[N], mxn;


int main() {
    scanf("%d", &T);
    for (int i = 1; i <= T; i++)
        scanf("%d%d", &n[i], &k[i]);
    mxn = *max_element(n + 1, n + 1 + T);
    for (int i = 1, j = 1;; i += 2, j++) {
        p[i] = (3 * j * j - j) >> 1;
        if (p[i] > mxn)break;
        p[i + 1] = (3 * j * j + j) >> 1;
        if (p[i + 1] > mxn)break;
    }
    dp[0] = 1;
    for (int i = 1; i <= mxn; i++)
        for (int j = 1; p[j] <= i; j++) {
            if ((j + 1) >> 1 & 1) add(dp[i], dp[i - p[j]]);
            else sub(dp[i], dp[i - p[j]]);
        }
    for (int i = 1; i <= T; i++) {
        int ans = dp[n[i]];
        for (int j = 1; 1ll * k[i] * p[j] <= n[i]; j++) {
            if ((j + 1) >> 1 & 1)sub(ans, dp[n[i] - k[i] * p[j]]);
            else add(ans, dp[n[i] - k[i] * p[j]]);
        }
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sky123_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值