hdu 2049

这个题,非常不错。有几个知识点,在这里说一下。

第一:组合数学中的错排问题。

#include<iostream>
#include<string>
#include<STDIO.H>
using namespace std;
__int64 a[21];
__int64  fab(int n)
{
    if(n==0||n==1)
        return 1;
    else
        return fab(n-1)*n;
}
int main()
{
	int test;
	cin>>test;
	while(test--)
	{
		int n,m;
		a[0]=0;
		a[1]=0;
		a[2]=1;
		a[3]=2;
		//cout<<fab(8)<<endl;
		for(int i=4;i<21;i++)
		{
			a[i]=(i-1)*(a[i-1]+a[i-2]);
		}
		cin>>n>>m;
		__int64 ans=fab(n)/fab(m)/fab(n-m)*a[m];
        printf("%I64d\n", ans);
	}
	return 0;
}

这是在wikipedia找到的资料。


简要说明如下:

研究错排问题的方法 

递推数列法 

对于排列数较多的情况,难以采用枚举法这时可以用递归思想推导错排数的递推公式。

显然D1=0,D2=1当n≥3时,不妨设n排在了第k位,其中k≠n,也就是1≤k≤n-1。那么我们现在考虑第n位的情况

  • 当k排在第n位时,除了n和k以外还有n-2个数,其错排数为Dn-2
  • 当k不排在第n位时,那么将第n位重新考虑成一个新的“第k位”,这时的包括k在内的剩下n-1个数的每一种错排,都等价于只有n-1个数时的错排(只是其中的第k位会换成第n位)其错排数为Dn-1

所以当n排在第k位时共有Dn-2+Dn-1种错排方法,又k有从1到n-1共n-1种取法,我们可以得到:

D n=(n-1)(D n-1+D n-2

第二点:这道题WA了几次,原因在于,全排列输出的的时候,我用(m!*(m-n)!).很明显,这种做法会超出long int的范围。所以要记住这一点。
另外 一小点。就是输出long int 要用这种格式%I64d
最后,上代码。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值