首页 > 代码库 > HDU 1521

HDU 1521

指数型生成函数。做这题时,回去看看组合数学才知道,指数生成函数求的就是多重集合的r排列数。

#include <iostream>#include <cstdio>#include <algorithm>#define N 15using namespace std;struct PQ{	int p,q;};PQ c1[N],c2[N];int num[N];PQ cal;int Q[N];int gcd(int a,int b){	if(b==0) return a;	return gcd(b,a%b);}PQ addsum(PQ a,PQ b){	PQ tmp;	tmp.q=a.q*b.q;	tmp.p=a.p*b.q+a.q*b.p;	int g=gcd(max(tmp.p,tmp.q),min(tmp.p,tmp.q));	tmp.p/=g; tmp.q/=g;	return tmp;}int main(){	int n,m,ptmp,qtmp;	Q[0]=1;	for(int i=1;i<N;i++)	Q[i]=Q[i-1]*i;	while(scanf("%d%d",&n,&m)!=EOF){		for(int i=1;i<=n;i++)		scanf("%d",&num[i]);		for(int i=0;i<N;i++){			c1[i].p=c2[i].p=0;			c1[i].q=c2[i].q=1;		}		for(int i=0;i<=num[1];i++)		c1[i].p=1,c1[i].q=Q[i];		for(int i=2;i<=n;i++){			for(int j=0;j<N;j++){				for(int k=0;k+j<N&&k<=num[i];k++){					ptmp=1,qtmp=Q[k];					cal.p=ptmp*c1[j].p;cal.q=qtmp*c1[j].q;					ptmp=gcd(max(cal.p,cal.q),min(cal.p,cal.q));					cal.p/=ptmp; cal.q/=ptmp;					c2[k+j]=addsum(cal,c2[k+j]);				}			}			for(int j=0;j<N;j++)			c1[j]=c2[j],c2[j].p=0,c2[j].q=1;		}		printf("%d\n",c1[m].p*Q[m]/c1[m].q);	}	return 0;}

  

HDU 1521