列表

详情


NC19950. [CQOI2017]老C的键盘

描述

老 C 是个程序员。     
作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序 在某种神奇力量的驱使之下跑得非常快。小 Q 也是一个程序员。有一天他悄悄潜入了老 C 的家中,想要看看这个 键盘究竟有何妙处。他发现,这个键盘共有n个按键,这n个按键虽然整齐的排成一列,但是每个键的高度却互不相同 。聪明的小 Q 马上将每个键的高度用 1 ~ n 的整数表示了出来,得到一个 1 ~ n 的排列 h1, h2,..., hn 。为了回去之后可以仿造一个新键盘(新键盘每个键的高度也是一个 1 ~ n 的排列),又不要和老 C 的键盘完全一样,小 Q 决定记录下若干对按键的高度关系。作为一个程序员,小 Q 当然不会随便选几对就记下来,而是选了非常有规律的 一些按键对:对于 i =2,3, ... , n,小 Q 都记录下了一个字符 < 或者 > ,表示 hi/2 < hi 或者hi/2> h 。于是,小 Q 得到了一个长度为n-1的字符串,开开心心的回家了。
现在,小 Q 想知道满足他所记录的高度关系的键盘有多少个。虽然小 Q 不希望自己的键盘和老 C 的完全相同,但是完全相同也算一个满足要求的键盘。答案可能很大,你只需要告诉小 Q 答案 mod 1,000,000,007 之后的结果即可。

输入描述

输入共 1 行,包含一个正整数 n 和一个长度为 n - 1 的只包含 < 和 > 的字符串,分别表示键盘上按键的数量,和小 Q 记录的信息,整数和字符串之间有一个空格间隔。

输出描述

输出共 1 行,包含一个整数,表示答案 mod 1,000,000,007后的结果。

示例1

输入:

5 <>><

输出:

3

说明:

共5个按键,第1个按键比第2个按键矮,第1个按键比第3个按键高,第2个按键比第4个
按键高,第2个按键比第5个按键矮。
这5个按键的高度排列可以是 2,4,1,3,5 , 3,4,1,2,5 , 3,4,2,1,5 。

示例2

输入:

5 <<<<

输出:

8

说明:

这5个按键的高度排列可为 (1,2,3,4,5) , (1,2,3,5,4) , (1,2,4,3,5) , (1,2,4,5,3) , (1,2,5,3,4) ,

(1,2,5,4,3) , (1,3,2,4,5) , (1,3,2,5,4) 。

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 4ms, 内存消耗: 1364K, 提交时间: 2023-02-17 19:13:17

#include <cstdlib>
# include <iostream>
# include <algorithm>
# include <cstdio>
# include <cmath>
# include <iomanip>
# include <cstring>
# include <queue>
# include <map>
# define LL long long
# define imax(a , b) ( (a) > (b) ? (a) : (b))
# define imin(a , b) ( (a) < (b) ? (a) : (b))
# define rl ro << 1
# define rr ro << 1 | 1
using namespace std;
const LL N = 100 + 511 , oo = 0x3f3f3f3f , M = 1e9 + 7;
char s[N];
LL n , f[N][N] , t[N] ,sz[N] ,c[N][N];
void dfs(LL x)
{
	sz[x] = 1 , f[x][1] = 1;

	for (LL p = 0; p <= 1; ++p)
	{
		LL y = x * 2 + p;
		if (y > n) break;

		dfs(y);

		for (LL i = 0; i <= n; ++i) t[i] = f[x][i] , f[x][i] = 0;

		for (LL i = 1; i <= sz[x]; ++i)
			for (LL j = 1; j <= sz[y]; ++j)
				if (s[y] == '>')
					for (LL k = i + j; k <= i + sz[y]; ++k)
						(f[x][k] += t[i] * f[y][j] % M * c[k - 1][i - 1] % M * c[sz[x] + sz[y] - k][sz[x] - i] % M) %= M;
				else
					for (LL k = i; k < i + j; ++k)
						(f[x][k] += t[i] * f[y][j] % M * c[k - 1][i - 1] % M * c[sz[x] + sz[y] - k][sz[x] - i] % M) %= M;

		sz[x] += sz[y];
	}
}
int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0) , cout.tie(0);

	cin>>n;
	cin>>s + 2;

	for (LL i = 0; i <= n; ++i)
	{
		c[i][0] = c[i][i] = 1;
		for (LL j = 1; j < i; ++j)
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M;
	}
	dfs(1);
	LL ans = 0;
	for (LL i = 1; i <= n; ++i)
		(ans += f[1][i]) %= M;
	cout<<ans;
}

C++(clang++ 11.0.1) 解法, 执行用时: 5ms, 内存消耗: 2828K, 提交时间: 2022-10-04 17:58:39

#include<bits/stdc++.h>
using namespace std ;
const int N = 505 , mod = 1e9 + 7 ;
#define ll long long
int n ;
char s[N] ;
vector<pair<int,int>> g[N] ;
int siz[N] ;
ll f[N][N],C[N][N],h[N] ;
void init(int n=N-5)
{
	C[0][0]=1 ;
	for(int i=1;i<=n;++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 ;
	}
}
void dfs(int x)
{
	f[x][1]=1 ; siz[x]=1 ;
	for(auto &z:g[x])
	{
		int y=z.first ;
		dfs(y) ;
		memcpy(h,f[x],sizeof(h)) ;
		memset(f[x],0,sizeof(f[x])) ;
		if(z.second==1)
		{
			for(int p1=1;p1<=siz[x];++p1)
				for(int p2=1;p2<=siz[y];++p2)
					for(int p3=p1;p3<=p1+p2-1;++p3)
						f[x][p3]=(f[x][p3]+C[p3-1][p1-1]*C[siz[x]+siz[y]-p3][siz[x]-p1]%mod*f[y][p2]%mod*h[p1]%mod)%mod ;
		}
		else
		{
			for(int p1=1;p1<=siz[x];++p1)
				for(int p2=1;p2<=siz[y];++p2)
					for(int p3=p1+p2;p3<=p1+siz[y];++p3)
						f[x][p3]=(f[x][p3]+C[p3-1][p1-1]*C[siz[x]+siz[y]-p3][siz[x]-p1]%mod*f[y][p2]%mod*h[p1]%mod)%mod ;
		}
		siz[x]+=siz[y] ;
	}
}
int main()
{
	scanf("%d%s",&n,s+1) ;
	init() ;
	for(int i=2;i<=n;++i)
		g[i/2].push_back({i,s[i-1]=='<'}) ;
	dfs(1) ;
	ll ans=0 ;
	for(int i=1;i<=n;++i) ans=(ans+f[1][i])%mod ;
	printf("%lld\n",ans) ;
	return 0 ;
}

上一题