指数型母函数的应用

指数型母函数

上一篇文章,我们介绍了最普通的母函数类型和它的应用,如果不理解母函数概念的可以先去看这篇文章了解https://editor.csdn.net/md/?articleId=115746930
今天我们继续介绍母函数的另一种类型,指数型母函数,我们都知道普通型母函数只能帮助我们解决组合问题,也就是选出这些东西的组合方式,不考虑排列的顺序。如果问题变化为排列问题,普通母函数显然无法很好的解决这种问题。在介绍指数型的母函数之前,先给大家一个经典排列问题思考一下
考虑n个元素组成的集合,其中a1重复了n1次,a2重复了n2次,…ak出现了nk次,其中n=n1+n2+L…
nk,求n个元素的全排列。
稍微思考这个问题,我们先假设所有东西都不重复,一共有n!种排列方式,现在考虑相同的情况,只需要除以每周元素相同个数的阶乘即可
在这里插入图片描述
如果要解决这个问题,我们吧问题举一个具体的例子,假设有8个元素,其中a1出现3次,a2出现2次,a3出现3次。我们先看从中求组合数时得到的母函数。
在这里插入图片描述
x的幂次实际代表最后选了几个物品,系数表示组合方式。
那么把问题改成排列,比如我们要从8个物品中农取4个做不同排列、我们不难发现,如果用2个a1和2个a3组合,排列数为4!/(2!2!)。如果一个a1和3个a3不同的排列数是4!/(1!3!)
所以所有排列的和形式转换为这样
在这里插入图片描述
如果要构造除这种形式的式子,我们可以改变母函数的定义方式。在这里插入图片描述
放到这道题里,构造的母函数应该是
在这里插入图片描述
把分母提取乘幂次的阶乘是因为这种排列要同时乘幂次的阶乘。所以选四个元素排列的答案应该是70。
到这里关于指数型母函数最基本的性质就介绍完了,接下来用两个例题来让大家更熟悉这个问题。

例题

一.排列组合

有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。
这道题就是刚刚介绍例题的模板。我们只需要在普通型母函数的基础上做出一点改动就行了。

#include <bits/stdc++.h>
using namespace std;
const int N=21;
double c1[N],c2[N];
int val[N],f[N],n,m;
void init(){//先预处理除阶乘
	f[0]=1;
	for (int i=1;i<N;i++)f[i]=f[i-1]*i;
}
int main() {
	init();
    while (~scanf("%d%d",&n,&m)){
    	for (int i=0;i<n;i++)scanf("%d",&val[i]);
    	memset(c1,0,sizeof(c1));
    	memset(c2,0,sizeof(c2));
    	for (int i=0;i<=val[0];i++)
    		c1[i]=1.0/f[i];
    	for (int i=1;i<n;i++){
    		for (int j=0;j<=m;j++)
    			for (int k=0;k+j<=m&&k<=val[i];k++)
    				c2[j+k]+=c1[j]/f[k];//这里相当于乘法,c1[j]代表的是前面括号的系数,后面代表后面括号的系数,
    		for (int j=0;j<=m;j++)
    			c1[j]=c2[j],c2[j]=0;
    	}
    	printf("%.0f\n",c1[m]*f[m]);//所有排列的分子都要乘选取个数的阶乘
    }
    return 0;
}

改变的几个细节就是有的地方要除f[k]。这道题应该是比较板子的指数型母函数,下面给大家介绍一个构造起来很有意思的指数型母函数

红色病毒问题

医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据可能非常庞大,你只要给出最后两位数字即可.
这道题的数据量很大,所以不可能还按照传统母函数的多项式乘法解决,但是题目很明显可以写成母函数的形式,在这里插入图片描述
光看到这里,问题还是无法得到解决,不过如果你学过高数,应该不会对这个形式感到陌生。
在这里插入图片描述
这个式子就是指数函数在x=0是展开的泰勒级数,也就是麦克劳林级数。下来问题就迎刃而解了
在这里插入图片描述

在这里插入图片描述
稍微进行一点推导,就能推出这个式子。当然如果你不知道指数函数是怎样。其实也没关系,我们只需要自己设f(x)等于这个东西,自己构造一个函数也能达到一样的效果,只用化简在构造回去就能解决问题.所以很多时候,我们需要不用了解泰勒函数的具体展开只需要自己构造函数也能达到相同的效果,只是泰勒函数的指数函数形式比较常见,遇到更多问题,可以更灵活的解决。公式退出来之后,只用写快速幂就能通过这道题目了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=100;
int T;
ll n;
ll ksm(ll a,ll b){ll ans=1;a%=mod;while(b){if(b&1)ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
int main() {
    while (~scanf("%d",&T)){
        if (T==0)return 0;
        for (int i=1;i<=T;i++){
            scanf("%lld",&n);
            printf("Case %d: %lld\n",i,(ksm(4,n-1)+ksm(2,n-1))%mod);
        }
        printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值