题解:洛谷 P1313 计算系数

【题目来源】

洛谷:P1313 [NOIP 2011 提高组] 计算系数 - 洛谷

【题目描述】

给定一个多项式 \((by+ax)^k\),请求出多项式展开后 \(x^n\times y^m\) 项的系数。

【输入】

输入共一行,包含 \(5\) 个整数,分别为 \(a,b,k,n,m\),每两个整数之间用一个空格隔开。

【输出】

输出共一行,包含一个整数,表示所求的系数。

这个系数可能很大,输出对 \(10007\) 取模后的结果。

【输入样例】

1 1 3 1 2

【输出样例】

3

【核心思想】

  1. 问题分析:给定多项式 \((by+ax)^k\),求展开后 \(x^n \times y^m\) 项的系数。由于 \(n + m = k\),问题转化为求展开式中 \(x^n\) 项的系数。这是一个线性DP问题,利用递推关系逐层计算多项式展开系数。

  2. 算法选择

    • 线性DPf[i][j] 表示 \((by+ax)^i\) 展开式中 \(x^j\) 项的系数
    • 递推关系:当前层系数由上一层系数推导而来
    • 取模处理:结果对 \(10007\) 取模,每一步运算后取模防止溢出
  3. 关键步骤

    • 初始化\((by+ax)^1 = by + ax\)
      • f[1][0] = b\(x^0\)(即 \(y^1\))项的系数为 \(b\)
      • f[1][1] = a\(x^1\)(即 \(y^0\))项的系数为 \(a\)
    • 状态转移:对于 \(i\)\(2\)\(k\)\(j\)\(0\)\(i\)
      • f[i][0] = f[i-1][0] * b\(x^0\) 项只能由上一层 \(x^0\) 项乘 \(by\) 得到
      • f[i][j] = f[i-1][j] * b + f[i-1][j-1] * a\(x^j\) 项可由上一层 \(x^j\) 项乘 \(by\)\(y\) 指数加1)或上一层 \(x^{j-1}\) 项乘 \(ax\)\(x\) 指数加1)得到
      • 每次运算后对 \(10007\) 取模
    • 答案获取f[k][n] 即为 \(x^n \times y^m\) 项的系数
  4. 时间/空间复杂度

    • 时间复杂度:\(O(k^2)\),外层 \(k\) 层,内层最多 \(i\)
    • 空间复杂度:\(O(k^2)\),二维DP数组(可优化为 \(O(k)\)
  5. 线性DP求多项式展开系数的核心思想

    • 递推思维:将 \((by+ax)^k\) 的展开问题分解为逐层递推,由 \((by+ax)^{i-1}\) 推导 \((by+ax)^i\)
    • 状态设计f[i][j] 精准定位到 \(x^j\) 项的系数,隐含 \(y\) 的指数为 \(i-j\)
    • 两种来源:每一项系数有两种来源——乘 \(by\)\(y\) 指数加1)或乘 \(ax\)\(x\) 指数加1)
    • 模运算处理:大数场景下每步取模,避免溢出
    • 适用于"多项式展开求特定项系数"类问题

【算法标签】

普及 #线性DP-一维

【代码详解】

#include <bits/stdc++.h>
using namespace std;

#define int long long  // 使用长整型防止溢出
const int N = 1005;    // 定义最大数组长度
const int mod = 10007;  // 模数

int a, b, k, n, m;     // 输入参数
int f[N][N];           // 动态规划数组

// f[i][j] 表示在(a+b)^i展开式中,x^n的指数为j的系数
// 注意:这里n是x的指数,j是当前x的指数

signed main()
{
    // 输入参数:a, b, k, n, m
    // (a+b)^k 展开式中 x^n * y^m 的系数,其中 n+m=k
    cin >> a >> b >> k >> n >> m;

    // 初始化:k=1的情况
    // (a+b)^1 = a + b
    f[1][0] = b % mod;  // 对应b,x的指数为0
    f[1][1] = a % mod;  // 对应a,x的指数为1

    // 动态规划:计算(a+b)^i的展开式系数
    for (int i = 2; i <= k; i++)
    {
        // 处理x指数为0的情况:只有b的贡献
        // (a+b)^i中x^0的系数 = (a+b)^(i-1)中x^0的系数 × b
        f[i][0] = f[i - 1][0] * b;
        f[i][0] %= mod;

        // 处理x指数从1到i的情况
        for (int j = 1; j <= i; j++)
        {
            // 递推公式:
            // f[i][j] = f[i-1][j] * b + f[i-1][j-1] * a
            // 解释:
            // 1. 从(a+b)^(i-1)中x^j的系数乘以b得到x^j项
            // 2. 从(a+b)^(i-1)中x^(j-1)的系数乘以a得到x^j项
            f[i][j] = (f[i - 1][j] * b) + (f[i - 1][j - 1] * a);
            f[i][j] %= mod;  // 取模防止溢出
        }
    }

    // 输出结果:x^n的系数(即x^n * y^m的系数)
    cout << f[k][n] << endl;

    return 0;
}

【运行结果】

1 1 3 1 2
2
posted @ 2026-06-25 19:14  团爸讲算法  阅读(10)  评论(0)    收藏  举报