关于普通生成函数的个人小结

这几天很多事情 只学了一点东西,对于生成函数的学习更只是片面,但是无奈今晚无心写题于是写小结
首先是普通生成函数
我觉得对于这个形式幂级数需要好好思考,并不是我们天天说的那个变量X,他更多只是一个形式作用,对于该类函数而言,他的卷积满足满足以下规则

普通生成函数通常拿来解决多重集组合数问题,说实话蛮巧妙的。
在这里由于实力有限 举董老师的例子

问题:有n种物品,每种物品有ai个,问取m个物品的组合数

典型组合数的问题,其实不学生成函数还真写不来 因为我组合数不太行

思路

设从每种物品中取bi个,0<=bi<=ai,
m=Σ(n,i=1)bi,对于每一组bi中选多选少方案数的贡献都是1,比如 3个A,一个B 这个方案就是AAAB 贡献总共是一个取法,那么最值答案是什么?其实就是满足b1+b2+....=m 的方案和

对于生成函数的构造,第一种物品的生成函数为(1,x,x2......xa1)什么意思 就是选0个,1个,2个...那后面第二种我就不重复写下去了 最终相乘然后进行取吗,其实就是高中组合取最终让x的幂为m即可,然后x^m的系数就是答案,就是高中组合呗,说实话这个以前还是azx教我的。。。。


最后5就是答案

例题 HDU 2152
有n种水果 每种水果选购的个数都在(ai,bi)之间,买m个水果有多少种购买方案

int calc()
{

	for(int i=a[1];i<=b[1];i++)
		c[i]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			for(int k=a[i];k<=b[i];k++)
			{
				d[j+k]=c[j]; 
			}
			for(int j=0;j<=m;j++)
			{
				c[j]=d[j],d[j]=0;
			}
		}
	}
	return c[m];
}

还有hdu的另外一个例题

#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
using namespace std;
const int range=2e5+10;
int n;
int a[range];
int b[range];
int c[range];
int d[range];
void solve()
{
	b[1]=1;
	b[2]=2;
	b[3]=5;
	cin>>a[1]>>a[2]>>a[3];
	int maxn=a[1]*1+a[2]*2+a[3]*5;
	for(int i=0;i<=maxn;i++)c[i]=d[i]=0;
	for(int i=0;i<=a[1];i++)c[i]=1;
	for(int i=2;i<=3;i++)
	{
		for(int j=0;j<=maxn;j++)
		{
			for(int k=1;k<=a[i]&&k*b[i]+j<=maxn;k++)
			{
				d[j+k*b[i]]+=c[j];
			}
		}
		for(int j=0;j<=maxn;j++)
		{
			c[j]=d[j],d[j]=0;
		}
	}
	int x=1;
	while(x<=maxn && c[x]) x++;
	cout<<x<<endl;//懒的
}
signed main()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	solve();
	
	return 0;
	
	
} 
posted @ 2025-04-16 19:55  LteShuai  阅读(12)  评论(0)    收藏  举报