错排

意义:n个不同的元素,每个元素都不在自己原来位置的排列方案数。

递推式:D(n) = (n-1)(D(n-2) + D(n-1)),D(0) = 1,D(1) = 0, D(2) = 1。

通项:D(n) = n! (1/0! - 1/1! + 1/2! - 1/3! - ..... + (-1)^n/n!)

代码:

void Init(){
	d[0] = 1,d[1] = 0,d[2] = 1;     //不要少了d[0]
	for(int i=3;i<N;i++)
		d[i] = (i-1) * (d[i-1] + d[i-2]);
}

 

lightoj1095:

题意:共n个数,前m个位置恰号有k个在自己的位置上。

题解:

  • 在前m个选k个在自己的位置上,有\binom{m}{k}种选法;

  • 后面的(n-m)个数错排的个数不确定,所以我们以此枚举有i个数在自己位置上。

  • 所以不在自己位置上的就是(n-k-i) 。

  • 公式为ans = \binom{m}{k}{\sum_{0}^{n-m}}\binom{n-m}{i}*D(n-k-i)

#include <bits/stdc++.h>
#define mod(x) ((x) % MOD)
using namespace std;
typedef long long ll;
int const MOD = 1e9 + 7;
int const N = 1000 + 10;
int n,m,k,T;
ll d[N],c[N][N];
void Init(){
	d[0] = 1,d[1] = 0,d[2] = 1;
	for(int i=3;i<N;i++)
		d[i] = mod((i-1) * (d[i-1] + d[i-2]));
	for(int i=0;i<N;i++){
		c[i][i] = c[i][0] =1;
		for(int j=1;j<i;j++)
			c[i][j] = mod(c[i-1][j-1]+c[i-1][j]);
	}
}
ll solve(){
	ll ans = 0;
	for(int i=0;i<=n-m;i++)
		ans = mod(ans + mod(c[n-m][i] * d[n-k-i]));
	return mod(ans * c[m][k]);
}
int main(){
	Init();
	scanf("%d",&T);
	int caser = 0;
	while(T--){
		cin>>n>>m>>k;
		printf("Case %d: %lld\n",++caser,solve());
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值