计算系数
先导
根据高中的数学知识二项式定理,我们可以得到
\((x+y)^n=C_{n}^0x^ny^0+C_{n-1}^1x^{n-1}y1+...+C_{n}^nx^0y^n\)
我们可以这样理解,比如这样一个式子,\((x+y)^5\)
如果我们要求\(x^3y^2\)的系数,那么我们想象成有\(()()()()()\)个括号连续相乘,为了得到\(x^3y^2\)
我们需要从\(5\)个括号中选出\(3\)个来作为\(x\)相乘的项,即\(C_{5}^3\)\((x)^3\)
另外还剩下两个括号,我们选出\(2\)个括号作为\(y\)相乘的项,即\(C_{2}^2(y)^2\)
最后把这两个分散的项相乘得到\(C_{5}^3(x)^3C_{2}^2(y)^2\)
推广
那么进行推广我们可以得到
\((x+y+z)^n\)如果要求\(x^ay^bz^c\)的系数
还是想象成有\(n\)个括号连续相乘
从\(n\)个括号中选出\(a\)个凑成\(x^a\),即\(C_{n}^a(x)^a\)。
从剩下的\(n-a\)个括号选出\(b\)个凑出\(y^b\),即\(C_{n-a}^b(y)^b\)。
最后从剩下的\(n-a-b\)个括号中选出\(c\)个凑出\(z^c\),即\(C_{n-a-b}^c(z)^c\)
最后的最后把这些分散的项相乘就是最终\(x^ay^bz^c\)的系数
(注意,我这里之所以要把\(x,y,z\)外面带上括号,就是因为某些情况下,\(x\)前面的系数可能不为1,这个时候还要把\(x\)前面的系数也算上)
比如要求\(x^3y^2\)
\((2x+3y)^5=C_{5}^3(2x)^3C_{2}^2(3y)^2\)
有了上面的知识储备,下面的这道题一定就非常简单了
真题
给定一个多项式\((ax+by)^k\),请求出多项式展开后\(x^ny^m\)项的系数。
输入格式
共一行,包含 5 个整数,分别为 \(a,b,k,n,m\),每两个整数之间用一个空格隔开。
输出格式
输出共 1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007 取模后的结果。
数据范围
\(0≤n,m≤k≤1000\)
\(n+m=k\)
\(0≤a,b≤10^6\)
输入样例:
1 1 3 1 2
输出样例:
3
题解
从连续的\(k\)个括号中选出\(n\)个作为凑成\(x^n\)
\(C_{k}^n(ax)^n\)
从剩下的\(k-n\)个括号中选出\(m\)个凑成\(y^m\)
\(C_{k-n}^{m}(by)^m\)
最后答案\(C_{k}^n(ax)^n\)\(C_{k-n}^{m}(by)^m\)
所以我们的代码只需要处理
\(a^n\),\(b^m\),还有组合数的计算就行
代码
#include <cmath>
#include <iostream>
using namespace std;
const int mod = 10007;
const int N = 1010;
int a, b, k, n, m;
int c[N][N];
void init() {
for (int i = 0; i <= 1000; i++)
for (int j = 0; j <= i; j++) {
if (j == 0)
c[i][j] = 1;
else
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
}
}
int qmi(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = (long long)ans * a % mod;
a = (long long)a * a % mod;
b >>= 1;
}
return ans % mod;
}
int main() {
init(); //预处理出组合数
cin >> a >> b >> k >> n >> m;
cout << (long long)qmi(a, n) * qmi(b, m) * c[k][n] % mod;
return 0;
}