Typesetting math: 100%
博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

Increasing Subsequence —— 1I

Increasing Subsequence

题目描述

给出排列P,两个人轮流取数,每次取的数需要在之前该人取数的右边,且比当前取出来所有的数都要大。所有当前可选的数都将等概率随机的被当前决策人选中。问两个人期望取数的轮数。

范围

n5000

题解

概率dp,设fi,j表示第一个人上一步选了ai,第二个人选了aj,当前的答案。

  • ai>aj

fi,j=1+1c×k>j,ak>aifi,k

  • ai<aj

fi,j=1+1c×k>i,ak>ajfk,j

注意到计算时可以使用前缀和优化,复杂度O(n2)

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 5010;
const int mod = 998244353;
#define ll long long
int pow_mod(int a,int b) {
	int res = 1;
	while(b) {
		if(b & 1) res = 1ll * res * a % mod;
		a = 1ll * a * a % mod;
		b >>= 1;
	}
	return res % mod;
}
ll f[N][N];
ll sum[N];
int inv[N];
int a[N];
ll cnt[N];
int main () {
	int n;
	cin >> n;
	for(int i = 1;i <= n; ++i) {
		cin >> a[i];
	}
	for(int i = 1;i <= n; ++i) {
		inv[i] = pow_mod(i,mod - 2);
	}
	
	for(int i = n;i >= 1; --i) {
		ll s = 0;
		ll c = 0;
		for(int j = n;j >= 0; --j) {
			if(i == j) continue;
			if(a[i] > a[j]) {
				f[i][j] = (1 + s * inv[c]) % mod;
				sum[j] = (sum[j] + f[i][j]) % mod;
				cnt[j] ++;
			}
			else {
				f[i][j] = (1 + sum[j] * inv[cnt[j]]) % mod;
				s = (s + f[i][j]) % mod;
				c ++;
			}
		}
	}
	ll ans = 0;
	for(int i = 1;i <= n; ++i) {
		ans = (ans + f[i][0]) % mod;
	}
	cout << 1ll * ans * inv[n] % mod << endl;
	return 0;
}
						
						
posted @   Allorkiya  阅读(48)  评论(0编辑  收藏  举报
编辑推荐:
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
阅读排行:
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
· 程序员转型AI:行业分析
· 重磅发布!DeepSeek 微调秘籍揭秘,一键解锁升级版全家桶,AI 玩家必备神器!
点击右上角即可分享
微信分享提示