暑期总结

本文介绍了一个选拔队员问题的解决方案,该问题要求计算特定条件下座位安排的方法数量,并通过矩阵快速幂的方法进行高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

选拔队员题解

题目

背景
随着 WZOI 的老一辈人员的离开,WZOI 的人数越来越少了。CJH 教练于是想选拔一些人
进入团队。
问题描述
这一天,许多的学生齐聚在机房的门口,等待这 CJH 教练的出现。。。
CJH 教练过了不久就来了,他看见那么多人来参加。虽然十分高兴,但是机房的位置十
分有限,于是他要淘汰一部分人。
CJH 教练说:“各位同学,十分高兴你们能来到这个机房。但是机房内的电脑的数目十分
有限,现在如果你们能答出下面这个问题,那么你们就能成为团队的一份子。注意਀,问题
是这样子的:‘机房内总共有 N(这个值 CJH 教练会告诉你)个位置,排列成一条直线,从
左往右编号为 1 到 N。现在你们中的 N 个人要坐到这 N 个位置上去,问总共有多少种安排
的方法。”
所有同学大呼太难了,于是 CJH 教练决定简化问题:从同学中选出若干个男生和若干多
个女生(即男女生的数目随便定 即男女生的数目随便定)安排到机房内的 N 个位置上去,要求任意两位女生不能
相邻(即任意两个女生之间必须有至少一个男生 即任意两个女生之间必须有至少一个男生),问总共有多少种方法,你们姑且可以认
为所有男生是等价 所有男生是等价的,所有女生是等价 所有女生是等价的。
CJH 为了再次降低难度,他只要求你将方案种数 mod M 即可。
当然,由于这个问题简化之后太简单了,于是 CJH 会用不同的 N 提问多次,这样他就可
以淘汰许多没能力的人了。
为了能顺利进入 WZOI,许多同学向 WZOI 的朋友求救。显然你就是他们的救星了,现在
将 CJH 教练的问题告诉你,要求你输出正确答案。
输入格式
输入数据第一行包৿两个整数 T,M,分别表示测试数据的组数和要将结果 mod M;
接下来 T 行,每行有一个整数 N,表示机房里总共有 N 个位置。
输出格式
输出数据共 T 行,每行一个整数 S,表示总的方案数 mod M 之后的那个数。

题解

矩阵加速
可以递推得出,是个斐波那契数列;
我做这道题的时候虽然推出来了斐波那契数列,但是一时没有想到矩阵加速,打的好像也不对,于是爆零,以下是ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read()
{
	char c;ll x=0;c=getchar();
	while(!isdigit(c)){c=getchar();}
	while(isdigit(c)){x=x*10+(c-'0');c=getchar();}
	return x;
}
ll n,t,m;
struct myjuzhen
{
	ll a[3][3];
};
myjuzhen mul(myjuzhen c,myjuzhen b)
{	
	myjuzhen ans;
	for(register int i=1;i<=2;++i)
	{
		for(register int j=1;j<=2;++j)
		{
			ans.a[i][j]=0;
		}
	}
	for(register int i=1;i<=2;++i)
	{
		for(register int j=1;j<=2;++j)
		{
			for(register int k=1;k<=2;++k)
			{
				ans.a[i][j]=(ans.a[i][j]+b.a[i][k]*c.a[k][j]%m)%m;
			}
		}
	}
	return ans;
}
myjuzhen qp(int b)
{
	myjuzhen base,ans;
	base.a[1][1]=base.a[1][2]=base.a[2][1]=1,base.a[2][2]=0;
	ans.a[1][1]=ans.a[2][2]=1;ans.a[1][2]=ans.a[2][1]=0;
	while(b)
	{
		if(b&1) ans=mul(ans,base);
		base=mul(base,base);
		b>>=1;
	}
	return ans;
}
int main()
{
	freopen("seat.in","r",stdin);freopen("seat.out","w",stdout);
	t=read(),m=read();
	while(t--)
	{
		n=read();
		if(n==1)
		{
			printf("%d\n",2%m);continue;
		}
		if(n==2)
		{
			printf("%d\n",3%m);continue;
		}myjuzhen ans;
		ans=qp(n-2);
		printf("%lld\n",(ans.a[1][1]*3+ans.a[1][2]*2)%m);
	}
	fclose(stdin),fclose(stdout);return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值