「NOIP模拟」抢座位【搜索+剪枝】

在这里插入图片描述

对于所有方案,必须满足的是 m m 个人的位置是否合法。

m m 又很小,考虑去搜索安排。

我们去 d f s dfs m m 个人。

假设第 i i 个已经安排座位的人的编号为 x x ,需要坐到 y y ,那么就需要坐在 x x ~ y 1 y-1 之间的人都在 i i 之前选择位置。

我们根据这个来搜索,顺便剪枝。

#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define pb push_back
#define pll pair<ll,ll>
#define make make_pair
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
#define res(i,x) for(ll i=head[x];i;i=nxt[i])
using namespace std;

const ll N=1e2+5;
const ll Inf=1e18;

ll n,m,mod,ans,s[N],fac[N],C[N][N];

struct node {
	ll p,q;
	bool operator < (const node &a) const {
		return p<a.p;
	}
}seat[30];

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

inline ll add(ll x,ll y) {
	return x+y>=mod?x+y-mod:x+y;
}

inline ll mul(ll x,ll y) {
	return x*y%mod;
}

int check(int id) {
	ll ret=s[id]-seat[id].q;

	vector<pll>v;

	rel(i,0,id) {
		if(s[id]>=seat[i].q&&s[id]<=s[i]) return -1;
		
		if(s[i]>=seat[id].q&&s[i]<s[id]) v.pb(make(max(seat[id].q,seat[i].q),s[i]));
	}
	
	sort(v.begin(),v.end());
	
	rel(i,1,v.size()) {
		if(v[i].first-1<=v[i-1].second) {
			v[i].first=v[i-1].first;
			v[i].second=max(v[i].second,v[i-1].second);v[i-1]=make(0,-1);
		}
	}
	
	rel(i,0,v.size()) ret-=v[i].second-v[i].first+1;
	
	return ret;
}

void dfs(ll id,ll sum,ll last) {
	if(id==m) {
		ans=add(ans,mul(sum,fac[last]));return ;
	}
	
	rep(i,seat[id].q,min(n,seat[id].q+seat[id].p-1)) {
		s[id]=i;
		
		ll ret=check(id);
		
		if(ret>-1) dfs(id+1,mul(sum,mul(C[last][ret],fac[ret])),last-ret+seat[id+1].p-seat[id].p-1);
	}
}

int main() {
	n=read(),m=read(),mod=read();
	
	rel(i,0,N) C[i][0]=1%mod;
	
	rel(i,1,N) rep(j,1,i) C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	
	fac[0] = 1;
	
	rep(i,1,n) fac[i]=mul(fac[i-1],i);
	
	rel(i,0,m) seat[i].p=read(),seat[i].q=read();
	
	sort(seat,seat+m);
	
	seat[m].p=n+1;
	
	dfs(0,1,seat[0].p-1);
	
	printf("%lld\n",ans);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/83547491