HDU 1521

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 15

using 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
",c1[m].p*Q[m]/c1[m].q);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4007062.html