列表

详情


NC20008. [HEOI2013]SAO

描述

Welcome to SAO ( Strange and Abnormal Online)。这是一个 VR MMORPG, 含有 n 个关卡。但是,挑战不同关卡的顺序是一个很大的问题。

有 n – 1 个对于挑战关卡的限制,诸如第 i 个关卡必须在第 j 个关卡前挑战, 或者完成了第 k 个关卡才能挑战第 l 个关卡。并且,如果不考虑限制的方向性, 那么在这 n – 1 个限制的情况下,任何两个关卡都存在某种程度的关联性。即, 我们不能把所有关卡分成两个非空且不相交的子集,使得这两个子集之间没有任 何限制。

输入描述

第一行,一个整数T,表示数据组数。
对于每组数据,第一行一个整数n,表示关卡数。
接下来n–1行,每行为“i sign j”,其中0 ≤ i,j ≤ n–1且i≠j,sign为“ < ”或者“ > ”,表示第i个关卡必须在第j个关卡前/后完成
T ≤ 5,1 ≤ n ≤ 1000

输出描述

对于每个数据,输出一行一个整数,为攻克关卡的顺序方案个数,mod1,000,000,007输出。

示例1

输入:

2 
5 
0 < 2 
1 < 2 
2 < 3 
2 < 4 
4 
0 < 1 
0 < 2 
0 < 3

输出:

4
6

原站题解

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

C++(clang++ 11.0.1) 解法, 执行用时: 86ms, 内存消耗: 16308K, 提交时间: 2022-09-30 15:58:53

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
const int mod = 1e9 + 7 , N = 2005 ;
int jc[N],inv[N] ;
int qsm(int a,int b)
{
	int ans=1 ;
	while(b)
	{
		if(b&1) ans=(ll)ans*a%mod ;
		a=(ll)a*a%mod ; b>>=1 ;
	}
	return ans ;
}
void init(int n=N-1)
{
	jc[0]=1 ;
	for(int i=1;i<=n;++i) jc[i]=(ll)jc[i-1]*i%mod ;
	inv[n]=qsm(jc[n],mod-2) ;
	for(int i=n;i>=1;--i) inv[i-1]=(ll)inv[i]*i%mod ;
}
int C(int n,int m)
{
	return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod ;
}
int calc(int x,int y)
{
	return (ll)jc[x+y]*inv[x]%mod*inv[y]%mod ;
}
int n ;
vector<pair<int,int>> g[N] ;
int f[N][N],h[N],siz[N] ;
int sum(int x,int l,int r)
{
	return (f[x][r]-f[x][l-1]+mod)%mod ;
}
void dfs(int x,int fa)
{
	siz[x]=1 ; f[x][1]=1 ;
	for(auto &y:g[x])
	{
		int z=y.first ;
		if(z==fa) continue ;
		dfs(z,x) ;
		memcpy(h,f[x],sizeof(h)) ;
		memset(f[x],0,sizeof f[x]) ;
		if(y.second==1)
		{
			for(int i=1;i<=siz[x];++i)
				for(int j=i;j<siz[z]+i;j++)
					(f[x][j]+=(ll)C(j-1,i-1)*C(siz[x]+siz[z]-j,siz[x]-i)%mod*h[i]%mod*sum(z,j-i+1,siz[z])%mod)%=mod ;
		}
		else
		{
			for(int i=1;i<=siz[x];++i)
				for(int j=i+1;j<=siz[z]+i;j++)
					(f[x][j]+=(ll)C(j-1,i-1)*C(siz[x]+siz[z]-j,siz[x]-i)%mod*h[i]%mod*sum(z,1,j-i)%mod)%=mod ;
		}
		siz[x]+=siz[z] ;
	}
	for(int i=2;i<=siz[x];++i) (f[x][i]+=f[x][i-1])%=mod ;
}
void solve()
{
	scanf("%d",&n) ; char ch ;
	for(int i=1;i<=n;++i) g[i].clear() ;
	memset(f,0,sizeof(f)) ;
	memset(siz,0,sizeof(siz)) ;
	for(int i=1,x,y;i<n;++i)
	{
		scanf("%d %c %d",&x,&ch,&y) ; x++ ; y++ ; 
		g[x].push_back({y,ch=='<'}) ;
		g[y].push_back({x,ch=='>'}) ;
	}
	dfs(1,0) ;
	printf("%d\n",f[1][n]) ;
}
int main()
{
	init() ;
	int T ; scanf("%d",&T) ;
	while(T--) solve() ;
	return 0 ;
}

上一题