3884. 【NOIP2014模拟】电影院

Description

成对成对的人生赢家要去看电影了啦!身为FFF团的骨干,你当然不能坐视不管。但为首的人生赢家小W实在太神辣,你只敢搞一些小动作。
土豪小W包下了电影院的一个包厢,其中有 n 排 m 列座位;相应的,看电影的人共有 nm/2 对。你无力阻止一对人生赢家坐在同一排(这是他们的底线)(m是一个偶数),但你可以想办法让每一对情侣都不相邻。求方案数 mod P 的值。

Input

三个数 n, m , p

Output

每一对情侣在同一排但不相邻的安排方案数 mod P 的值。

Sample Input

2 4 10007

Sample Output

384
【样例说明】假设四对人生赢家分别是S-T,U-V,W-X,Y-Z
┏━━┓
┃SUTV┃
┃WYXZ┃  是一种基本方案
┗━━┛
将四对人生赢家任意互换,再将大小写字母任意互换,产生 4!*2^4=384 种合法方案。

Data Constraint

Solution

推了推式子没推出来,实际上,Ans(n,m)=Ans(1,m)^n*(nm/2)!*2^(nm/2)
先是一列的方案数的n次方,表示n行的不同的排列的方案(没有标号的)
(nm/2)!就是将每对情侣标号排列的方案数
再乘上2^(nm/2)是每对情侣的两个人的位置互换或者说是将每对情侣的两个人再标号的方案
那么问题转换为求一行的方案数
我们可以维护 F[i][j]表示某一行已有 i 对情侣其中 j 对相邻 的方案数,则 F[n][0]即为答案,状态数 n^2,转移复杂度 O(n),时间复杂度 n^2。
F[i][j]=F[i-1][j+2]*(j+2)*(j+1) //插入的当前一对情侣不相邻,均插入到某一对情侣中的情况
+F[i-1][j+1]*(j+1)*(i+i-j-2)*2 //插入的当前一对情侣不相邻其中一个插入到某一对情侣中情况
+F[i-1][j]*(i+i-j-1)*(i+i-j-2) //插入的当前一对情侣不相邻,但未插入到某一对情侣中的情况
+F[i-1][j]*j*2 //插入的当前一对情侣相邻,但未插入到某一对情侣中的情况
+F[i-1][j-1]*(i+i-j)*2; //当 j>0 时,插入当前一对情侣到某一对情侣中的情况
对于 100%的数据 令 ans(m)=Ans(1,m),观察 ans(m)的前几项不难得到 ans(m) = (4m2 − 2m) ∗ ans(m − 1) + (2m − 2) ∗ ans(m − 2)
归纳后得到 Ans(n,m)=2^n*(nm)!*A(m)n 其中 A(0) = 1 A(1) = 0 A(n) = (2n − 1) ∗ A(n − 1) + A(n − 2) 递推求解就能很好地满足题目的要求。

Code

#include<cstdio>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(register int i=a;i<=b;++i)
#define Fd(i,a,b) for(register int i=a;i>=b;--i)
#define N 10000004
using namespace std;
ll n,m,p,f[N],ans;
ll ksm(ll x,ll k){
	ll sum=1;
	while(k){
		if(k&1) sum=(sum*x)%p;
		k>>=1;x=(x*x)%p;
	}
	return sum;
}
I main(){
	scanf("%lld%lld%lld",&n,&m,&p);
	if((n*(m/=2ll))>=p){
		printf("0\n");return 0;
	}
	f[0]=1;f[1]=0;
	F(i,2,m) f[i]=((ll)(i*2ll-1ll)*f[i-1]%p+f[i-2])%p;
	ans=ksm(f[m],n);
	F(i,1,m*n) ans=(ans*(ll)i*2ll)%p;
	printf("%lld\n",ans);
	return 0; 
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值