uva 10105 Polynomial coefficients

数学题

题意:

多项式(x1+x2+...+xk)n.

输入nk(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);
    }
}

 

posted @ 2012-12-22 13:31  Titanium  阅读(513)  评论(0编辑  收藏  举报