BZOJ2729 [HNOI2012]排队(排列组合+高精度)

【题解】

   A(n,n)*( A(2,n+1)*A(m,n+3) + C(1,n+1)*A(2,2)*C(1,m)*A(m-1,n+2) )

= A(n,n)*( A(2,n+1)*A(m,n+3) + (n+1)*2*m*A(m-1,n+2) )

为防止数字过长导致复杂度太大,用long long压9位(防止乘爆)


【代码】

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 2000
#define MOD 1000000000ll
struct big
{
	long long s[LEN+5];
	big()
	{
		memset(s,0,sizeof(s));
	}
};
int get(big a)
{
	int i;
	for(i=1;i<LEN;i++)
		if(a.s[i]!=0) break;
	return i;
}
void jw(big& a)
{
	int i;
	for(i=LEN;i>0;i--)
	{
		a.s[i-1]+=a.s[i]/MOD;
		a.s[i]%=MOD;
	}
}
big cheng_num(big a,int b)
{
	int i;
	for(i=LEN;i>0;i--)
		a.s[i]*=b;
	jw(a);
	return a;
}
big cheng(big a,big b)
{
	big res;
	int i,j,ta=get(a),tb=get(b);
	for(i=LEN;i>=tb;i--)
	{
		for(j=LEN;j>=ta;j--)
			res.s[i+j-LEN]+=b.s[i]*a.s[j];
		jw(res);
	}
	return res;
}
big jia(big a,big b)
{
	big res;
	int i;
	for(i=LEN;i>0;i--)
		res.s[i]=a.s[i]+b.s[i];
	jw(res);
	return res;
}
big A(int m,int n)
{
	big res;
	int i;
	res.s[LEN]=1;
	for(i=n-m+1;i<=n;i++)
		res=cheng_num(res,i);
	return res;
}
void print(big a)
{
	int i,ta=get(a);
	printf("%lld",a.s[ta]);
	for(i=ta+1;i<=LEN;i++)
		printf("%09lld",a.s[i]);
}
int main()
{
	big t;
	int n,m,i,j,k;
	scanf("%d%d",&n,&m);
	if(m>n+3) printf("0");
	else print(   cheng(  A(n,n)  ,  jia( cheng(A(2,n+1),A(m,n+3)) , cheng_num(A(m-1,n+2),(n+1)*2*m) )  )   );
	return 0;
}


你可能感兴趣的:(高精度,排列组合,压位)