/****************************************************************************/
/* Binomio de Newton: desarrollo de (x+y)^n donde n es un entero            */
/* long. Usa LIP.                                                           */
/*                                                                          */
/* Jaime Suarez <mcripto@bigfoot.com> 2003                                  */
/* en http://elparaiso.mat.uned.es                                            */
/****************************************************************************/

#include "lip.h"

#include <stdio.h>


int comb(long m, long n, verylong *x);
int fact(long n, verylong *x);

main(int argc, char *argv[])
{
	long i,n;
	verylong coef=0;

	if (argc!=2) {
		printf("%s <n> desarrollo de (x+y)^n.\n",argv[0]);
		return 1;
	}
	n=atol(argv[1]);
	
	printf("(x+y)^%ld = \n",n);
	printf("x^%ld + ",n);
	for (i=1; i<n; i++) {
		comb(n,i,&coef);
		zwrite(coef);
		printf("x^%ld.y^%ld + ",n-i,i);
	}
	printf("y^%ld\n",n);
		
	return 0;
}

int comb(long m, long n, verylong *x)
{
	verylong a=0,b=0,c=0,d=0,e=0;

	if (m<n || m==0 || n==0) return 1;
	
	fact(m,&a);
	fact(n,&b);
	fact(m-n,&c);
	zmul(b,c,&d);
	zdiv(a,d,x,&e);	/* e, el resto deberia ser 0 */
	return 0;
}

int fact(long n, verylong *x)
{
	verylong fact=0, tmp=0, uno=0;
	
	if (n<0) return -1;
	if (n==0) { zone(x); return 0;}

	zone(&fact);
	zone(&uno);
	while(n >1) {
		zsmul(fact,n--,&tmp);
		zcopy(tmp, &fact);
	}
	
	zcopy(fact, x);
	return 0;
}