专栏文章

题解:P1386 座位安排

P1386题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miqeyj2m
此快照首次捕获于
2025/12/04 03:42
3 个月前
此快照最后确认于
2025/12/04 03:42
3 个月前
查看原文

思路

依题 dp
组合数学前面题解的 dl 已讲得清晰了,在这里不过多赘述。乘法原理。小学知识。
奉天承运,皇帝诏曰:
钦定 hzhhzh 数组,hzhi=后面“预定座位”的人数hzh_i=后面“预定座位”的人数。故坐不下时,即当 hzhi>ni+1hzh_i > n-i+1 时,应当挤挤凑合着坐判无解。
钦定 CC 矩阵,CjiC_j^i 表示从 max(j,i)\max(j,i) 个数中选 min(j,i)\min(j,i) 个数的方法和。易转移如下:Cji=(Cj1i1+Cji1)C_j^i=(C^{i-1}_{j-1}+C^{i-1}_j)
钦定 dpdp 矩阵,dpjidp_j^i 表示在编号大于等于 ii 的人中确定 jj 人之座位的方法总和数。易转移如下:dpji=k=0jdpjki1×Ckjdp_j^i=\sum_{k=0}^j dp_{j-k}^{i-1}\times C_k^j
敬告众卿:勿忘取 %。

码:

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
void dui(int x)
{
	cout<<"YES"<<" "<<x<<endl;
}
void cuo()
{
	cout<<"NO"<<endl;
}
int hzh[305],c[305][305],dp[305][305];
signed main()
{
	int  t;
	cin>>t;
	while(t--)
	{
		int n,m,mod;
		cin>>n>>m>>mod;
		bool flag=0;
		memset(hzh,0,sizeof(hzh));
		memset(dp,0,sizeof(dp));
		for(int i=0;i<=300;i++)
		{
			c[i][0]=c[i][i]=1;
			for(int j=1;j<=i;j++)	c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
			
		}
		for(int i=1;i<=m;i++)
		{
			int x;
			cin>>x;
			int y;
			cin>>y;
			hzh[y]++;
		}
		for(int i=n;i>=1;i--)	hzh[i]+=hzh[i+1];
		for(int i=1;i<=n;i++)
		{
			if(hzh[i]>n-i+1)
			{
				cuo();
				flag=1;
				break;
			}
		}
		if(flag==1)	continue;
		for(int i=0;i<=n;i++)
		{
			if(i)	dp[n+1][i]=0;
			else	dp[n+1][i]=1;
		}
		for(int i=n;i>=1;i--)
		{
			for(int j=0;j<=n-i+1-hzh[i]&&j>=0;j++)
			{
				for(int k=0;k<=j;k++) 
				{
					dp[i][j]=(dp[i][j]+c[j][k]*dp[i+1][j-k])%mod;
				}
			}
		}
		dui(dp[1][n-m]);
	}
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...