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

  

时间: 2024-10-11 14:43:44

HDU 1521的相关文章

排列组合 HDU - 1521 -指数型母函数

排列组合 HDU - 1521 一句话区分指数型母函数和母函数就是 母函数是组合数,指数型母函数是排列数 #include<bits/stdc++.h> using namespace std; #define maxn 12 double ans[maxn],tp[maxn],inv[maxn]; int n,m,a[maxn]; void init() { inv[0]=1; for(int i=1; i<=11; i++) inv[i]=inv[i-1]*i; } int main

hdu 1521 排列组合 —— 指数型生成函数

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1521 标准的指数型生成函数: WA了好几遍,原来是多组数据啊囧: 注意精度,直接强制转换(int)是舍去小数,会WA,+0.5再强制转换或输出 %.0lf 是四舍五入,能A. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace

HDU 1521 排列组合 指数型母函数

指数型生成函数公式(其中一个): #include<iostream> #include<string.h> #include<stdio.h> using namespace std; #define M 15 double fac[M]; void fun()//求n的阶乘 函数 { int i; fac[0]=1; for(i=1;i<=10;i++) fac[i]=i*fac[i-1]; } int main() { int n,m; int z[M];

HDU 1521 指数型母函数

方法一: DFS 方法二:生成函数 每个数可以重复一定次数,求排列组合数,这是裸的指数型生成函数: 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 double c1[15],c2[15]; 6 int a[15]; 7 int num[15]; 8 9 10 int main() { 11 12 a[0] = 1; 13 for(int i=1; i<13; i++) 14 a[i] = a[i-1]*i; 15 16 i

HDU 1521 排列组合

Problem Description 有n种物品,并且知道每种物品的数量.要求从中选出m件物品的排列数.例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种. Input 每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量. Output 对应每组数据输出排列数.(任何运算不会超出2^31的范围) Sample Input 2 2 1 1 Sample

HDU 1521 排列组合 搜索

排列组合 Problem Description 有n种物品,并且知道每种物品的数量.要求从中选出m件物品的排列数.例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种. Input 每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量. Output 对应每组数据输出排列数.(任何运算不会超出2^31的范围) Sample Input 2 2 1 1 Sa

指数型母函数理解

普通型母函数主要是求组合的方案数,而指数型母函数则是求多重排列数. 例如:设有8个元素,a1重复3次,a2重复2次,a3重复3次.从中取出r个集合,求其组合数. 推荐:http://www.wutianqi.com/?p=2644 对于代码的推荐:http://blog.csdn.net/a342374071/article/details/6537960 以hdu 1521为例: 有n种物品,并且知道每种物品的数量.要求从中选出m件物品的排列数.例如有两种物品A,B,并且数量都是1,从中选2件

母函数专题

1.Hdu 2082 找单词 题意:单词A-Z具有1-26的价值,现有字母A-Z的个数num[i],求问在不超过价值为五十的情况下,有多少种字母的组合数. 思路:用指数代表价值,价值又为数组的下标:用系数代表组成该价值的方案数,方案数为数组中存的值. 1 #include<iostream> 2 #include<memory.h> 3 using namespace std; 4 int re[55]; 5 int p1[55]; 6 int p2[55]; 7 int xx[2

HDU分类

模拟题, 枚举 1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 1049 1050 1057 1062 1063 1064 1070 1073 1075 1082 1083 1084 1088 1106 1107 1113 1117 1119 1128 1129 1144 1148 1157 1161 1170 1172 1177 1197 1200 1201 12