数学题
题意:
多项式(x1+x2+...+xk)n.
输入n和k(0<k,n<13),分别表示多项式次数和变元数。第二行为k个非负整数n1,n2,...nk,满足n1+n2+...nk=n.
输出多项式(x1+x2+...+xk)n展开后的(x1)^n1*(x2)^n2...(xn)^nk这一项的系数。
思路:
如果单单是(a+b)^n,那我们可以轻易地用二项式定理来解决系数的问题,但是现在变量有k个,要怎么办呢?
我们可以用一种递归的思想来看这道题,化繁为简,将一个没见过的问题转化为见过的
(x1+x2+x3……+xk-1+xk)^n=(Xk-1+xk)^n , 即我们把前面k-1项全部加起来用Xk-1替代
那么这个式子(Xk-1+xk)^n 就是我们熟悉的(a+b)^n
(x1)^n1*(x2)^n2...(xn)^nk这一项可以表示为 (Xk-1)^m * xk^nk , 那么这一项的系数是C(n,nk)
那么m是多少呢?显然是m=n-nk
这个和(a+b)^n , 展开后每一项都可以表示为 a^(n-nk)*b^nk 的道理是一样的
所以现在我们要解决 (X(k-1))^m
别忘了Xk-1^m=(x1+x2+x3……xk-1)^m = (Xk-2+xk-1)^m , 而我们是要其中特定的一项的系数,所以要开拆分, 转化为原式子对应的项就是 Xk-2^(m-nk-1) * xk-1^nk-1
这不就和刚才是一样的吗?
可想而知这项的系数是C(m,nk-1)=C(n-nk , nk-1)
所以可以递归解决,当然要写成迭代也是非常容易的
另外我们要多次用到组合数C(n,m),所以我们应该事先保存下来
用计算机来构建C一般利用杨辉三角
杨辉三角的第0层(这里我们从0开始标号)为1,从第1层开始,第i层的数字其实就是(a+b)^i的系数
我们用左对齐的形式来储蓄杨辉三角,对于每一层,我们需要构建的数字是第2个数字到第i个数字(因为第i层有i+1个数字,第1和第i+1个数字一定会1)
由杨辉三角性质和用左对齐的方式储存可知,a[i][j]=a[i-1][j]+a[i-1][j-1];
然后问题就解决了
#include <cstdio> #include <cstring> #define N 15 int c[N][N]; int main() { c[0][0]=c[1][0]=c[1][1]=1; for(int i=2; i<=13; i++) //行 { c[i][0]=c[i][i]=1; for(int j=1; j<i; j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } /* for(int i=1; i<=13; i++) { for(int j=0; j<=i; j++) printf("%d ",c[i][j]); printf("\n"); } */ int i,n,k,a[N]; long long sum; while(scanf("%d%d",&n,&k)!=EOF) { for(i=1; i<=k; i++) scanf("%d",&a[i]); sum=1; i=k; while(i>=1) { sum*=c[n][a[i]]; n-=a[i]; i--; } printf("%lld\n",sum); } }