列表

详情


NC20205. [JSOI2013]游戏中的学问

描述

大家应该都见过很多人手拉手围着篝火跳舞的场景吧?一般情况下,大家手 拉手跳舞总是会围成一个大圈,每个人的左手拉着旁边朋友的右手,右手拉着另一侧朋友的左手。 不过,如果每一个人都随机的拉住两个不同人的手,然后再慢慢散开,事情就变得有趣多了——此时大家依旧会形成圈,不过却可能会形成多个独立的圈。 
当然这里我们依然要求一个人的右手只能拉另一个人的左手,反之亦然。 
班里一共有N个同学,由1到N编号。Will想知道,究竟有多少种本质不 同的拉手方案,使得最终大家散开后恰好形成k个圈呢? 
给定两种方案,若存在一个人和他的一只手,满足在这两种方案中,拉着这只手的人的编号不同,则这两种方案本质不同。

输入描述

输入一行包含三个正整数N,k和P.
3 ≤ 3k ≤ N ≤ 3000,10^4 ≤ p ≤ 2×10^9

输出描述

输出文件的包含一行一个整数,表示本质不同的方案数对p的余数。
保证p一定是一个质数。

示例1

输入:

3 1 1000000009

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 42ms, 内存消耗: 12152K, 提交时间: 2021-08-09 08:26:37

#include<cstdio>
using namespace std;
int dp[3005][1005];
int main(){
	int n,k,p;
	scanf("%d%d%d",&n,&k,&p);
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=k;j++){
			dp[i][j]=(dp[i-1][j]*(i-1))%p;
			if(i>=3) dp[i][j]=(dp[i][j]+dp[i-3][j-1]*(i-1)%p*(i-2)%p)%p;
		}
	}	
	printf("%d",dp[n][k]);
	return 0;
} 

上一题