2020杭电多校第10场1004

题意:给你一个长度为n-1的序列,若a[i]=1,则b[i]>b[i+1];若a[i]=0,则b[i]<b[i+1]。问你根据这个给定的a序列能构造成多少满足条件的关于b的全排列。
思路:dp[i][j]表示放了i个数,第i个位置放j的情况总数。假如现在放到第i个位置,想要在第i个位置放置j。若a[i]=0,那么dp[i][j]=dp[i-1][1]+dp[i-1][2]+…+dp[i][j-1]。这里有一个问题,那就是会想到重复放置数的情况。比如,现在要放3,而前面已经放过。前一个集合为{1,3,2},那么变成{1,3,2,3}。我们可以将前面大于3的数都加1,那么就变成了{1,4,2,3},这样就满足了条件。所以也就没有重复放置数的问题了。若a[i]=1,那么dp[i][j]=dp[i-1][j]+dp[i-1][j+1]+dp[i-1][i-1],关于重复放置情况的分析与上面类似。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll T,n,a[5005],qz[5005],dp[5005][5005];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n;
		for(ll i=2;i<=n;i++) cin>>a[i];
		for(ll i=1;i<=n;i++)
			for(ll j=1;j<=n;j++) 
			    dp[i][j]=qz[j]=0;
		dp[1][1]=1;qz[1]=1;
		for(ll i=2;i<=n;i++){
			for(ll j=1;j<=i;j++){
				if(!a[i]) dp[i][j]=(dp[i][j]+qz[j-1])%mod;
				if(a[i]) dp[i][j]=(dp[i][j]+qz[i-1]-qz[j-1])%mod;
			}
			qz[1]=0;
			for(ll j=1;j<=i;j++){
                qz[j]=(qz[j-1]+dp[i][j])%mod;
            }
		}
		ll sum=0;
		for(ll i=1;i<=n;i++) sum=(sum+dp[n][i])%mod;
		cout<<(sum+mod)%mod<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值