B.Blcoks(2019武大校赛现场赛)(吉比特杯第二届湖北省程序设计大赛) 解题报告 Apare_xzc

B.Blcoks(2019武大校赛现场赛)(吉比特杯第二届湖北省程序设计大赛) 解题报告

xzc 2019/4/16

题意:
  n个柱子(n<=20),每个柱子有高度h和美丽值b,高度h各不相同,但b可能相同
  现在要选L个,高度升序,美丽值也升序,剩下的不能被看到要放在高度比它高的柱子的后面,求排列的种类数%998244353


输入形式:

n L
h1 h2 h3... hn
b1 b2 b3... bn

样例输入:

4 3
1 2 3 4
1 2 2 3

样例输出

3

思路:

  • 2^20,dfs即可
  • 先结构体按高度升序排
  • 然后从高往低选,dfs选出L个
  • 中间可以剪枝
  • 如果一个块不选(第i个),那么这个块可以放在所有比它高的柱子后面(n-i个,n-i种选择)
  • 最后选够L个,若前面第1个到第x个还没选,那么这个选择的答案要乘以(n-1)*(n-2)*…*(n-x) 预处理前缀积即可(要取模)

我的代码:

#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 100;
const int mod = 998244353;
int b[maxn],m,n;
int r[maxn];
LL sum[maxn];
LL ans;
void dfs(int pre,int cnt,int x,LL preAns)
{
	if(cnt==m)
	{
		preAns = preAns*sum[x]%mod;
		ans = (ans+preAns)%mod;
		return;
	}
	if(m-cnt>x) return;
	if(b[pre]>b[x]) //可以选
	{
		r[cnt+1] = x;
		dfs(x,cnt+1,x-1,preAns);
	}
	dfs(pre,cnt,x-1,preAns*(n-x)%mod);
}
int main()
{
    //freopen("in.txt","r",stdin);
    //frepen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    	vector<pair<int,int> > v(n);
    	For(i,0,n-1) scanf("%d",&v[i].first);
    	For(i,0,n-1) scanf("%d",&v[i].second);
    	sort(v.begin(),v.end());
    	For(i,1,n) b[i] = v[i-1].second; 
    	ans = 0;
    	sum[0] = 1;
    	For(i,1,n) sum[i] = sum[i-1]*(n-i)%mod;
    	r[1] = b[n];
    	dfs(n,1,n-1,1); 
    	printf("%lld\n",ans);
	}
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值