首页 > 其他分享 >[ARC104E] Random LIS 题解

[ARC104E] Random LIS 题解

时间:2023-07-19 18:25:26浏览次数:44  
标签:ARC104E int 题解 Random ret 1ll 值域 dp mod

[ARC104E] Random LIS 题解

Link
吐了,一下午就写了这一个题……主要是题解都说的很草率。然后上课的时候貌似讲的方法不是很能做(也许是我太菜了),总之我得写篇题解整理整理。
首先 \(n\) 很小,可以直接爆搜所有相对大小,即我们去搜索 \(1\) 到 \(n\) 的排名,排名可以一样(即 \(a_i\) 相等)。最长上升子序列直接暴力 dp;然后,我们可以根据这个排名以及各个点的值域确定出每个排名对应的值域上界(就是最小的那个)。每个排名所对应的值应该是严格单调递增的,这样,我们可以对这个排名进行 dp。设 $f_{i,j} $ 表示第 \(i\) 个排名选择第 \(j\) 个值域区间的方案数,这里的值域可以离散化。我们首先枚举第 \(i\) 个排名,然后枚举这个排名选择的值域区间 \(j\),由于可能一个值域区间能放很多个排名,所以我们还要枚举一个左端点 \(k\),表示 \([k, i]\) 中的排名全部从 \(j\) 中取,由于单调递增,所以相当于是从长度为 \(len\) 的区间内选择 \(i-k+1\) 个数。最后,我们枚举排名 \(k-1\) 选择的值域区间,转移即可。
方程:$ f_{i, j} = \sum_{k = 1}^{i} \sum_{o = 0}^{j-1} {len_j \choose i-k+1}f_{k-1, o} $
代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 8, mod = 1e9+7;



inline int fpow(int a, int b){
	int ret = 1;
	a%=mod;
	while(b){
		if(b & 1){
			ret = (1ll*ret*a)%mod;
		}
		b>>=1;
		a = (1ll*a*a)%mod;
	}
	return ret;
}

int  a[N], b[N], na[N];
int inv[N], fac[N];
inline int C(int n, int m){
	if(n<0 || m<0 || n<m) return 0;
	int ret = 1;
	for(int i = n; i>=n-m+1; --i) ret = (1ll*ret*i)%mod;
	return 1ll*ret*inv[m]%mod;
}
int n, nn;
void prework(){
	fac[0] = 1;
	for(int i = 1; i<=n; ++i){
		fac[i] = (1ll*fac[i-1]*i)%mod;
	}
	inv[n] = fpow(fac[n], mod-2);
	for(int i = n-1; i>=0; --i){
		inv[i] = (1ll*inv[i+1]*(i+1))%mod;
	}
}
bool vis[N];
int p[N];//相对位次 
int dp[N];
int mx;
int f[N][N];//表示第 i 个位次位于值域第 j 段的方案数。 
int h[N];//每一个位次的上界 
inline int calc(){
	memset(h, 0x3f, sizeof(h));
	int m = 0;
	for(int i = 1; i<=n; ++i){
		h[p[i]] = min(h[p[i]], a[i]);
		m = max(m, p[i]);
	}
	int tot = 0;
	for(int i = 1; i<=m; ++i){
		na[++tot] = h[i]; 
	}
	sort(na+1, na+tot+1);
	tot = unique(na+1, na+tot+1)-na-1;
	for(int i = 1; i<=m; ++i){
		h[i] = lower_bound(na+1, na+tot+1, h[i])-na;
	}//离散化 
	memset(f, 0, sizeof(f));
	f[0][0] = 1;
	for(int i = 1; i<=m; ++i){
		for(int j = 1; j<=h[i]; ++j){//枚举当前点选的值域 
			int mn = h[i];
			for(int k = i; k>=1; --k){//枚举这个值域控制的范围(左端点) 
				mn = min(h[k], mn);
				if(j > mn) break;
				for(int o = 0; o<j; ++o){
					if(!f[k-1][o]) continue;
					f[i][j] = (1ll*f[i][j]+1ll*C(na[j]-na[j-1], i-k+1)*f[k-1][o]%mod)%mod;
				} 
			}
		}
	}
	int ret = 0;
	for(int i = 1; i<=tot; ++i){
		ret = (1ll*ret+f[m][i])%mod;
	}
	return ret;
}
int ans = 0;
void dfs(int pos, int lim){
	if(pos>lim){
		for(int i = 1; i<=n; ++i){
			b[i] = p[i];
		}
		sort(b+1, b+n+1);
		for(int i = 1; i<=n; ++i){
			if(b[i]-b[i-1]>1) return;
		}
		mx = 0;
		for(int i = 1; i<=n; ++i){
			dp[i] = 1;
			for(int j = 1; j<i; ++j){
				if(p[i]>p[j]) dp[i] = max(dp[i], dp[j]+1);
			}
			mx = max(dp[i], mx);
		}//dp求最长上升子序列 
		ans = (1ll*ans+1ll*mx*calc()%mod)%mod;
		return;
	}
	for(int i = 1; i<=n; ++i){
		p[pos] = i;
		dfs(pos+1, lim);
	}
}
signed main(){
	scanf("%d", &n);
	prework();
	for(int i = 1; i<=n; ++i){
		scanf("%d", &a[i]);
	}

	dfs(1, n);
	int innv = 1;
	for(int i = 1; i<=n; ++i){
		innv = (1ll*innv*a[i])%mod;
	}
	innv = fpow(innv, mod-2);
	ans = 1ll*ans*innv%mod;
	ans = (ans+mod)%mod;
	printf("%d\n", ans);
	return 0;
}

标签:ARC104E,int,题解,Random,ret,1ll,值域,dp,mod
From: https://www.cnblogs.com/frostwood/p/17566420.html

相关文章

  • RTSP流媒体服务器LntonNVR(源码版)云服务平台下载录像后无法拖动时间轴的问题解决方案
    LntonNVR安防视频云服务平台是基于RTSP/Onvif协议的视频接入、处理及分发平台,可以分发出RTSP、RTMP、WS-FLV、HTTP-FLV、HLS、WebRTC等格式的视频流,可实现在全终端(PC、手机、平板、电子大屏/电视墙等)播放监控视频。有用户反馈,在使用LntonNVR下载录像时,下载后的录像时间无法拖动时间......
  • 【小学期实训】附加题题解——Good Karma
    [状压dp+容斥原理]实训附加题——GoodKarma目录[状压dp+容斥原理]实训附加题——GoodKarma题目描述题目输入格式输出格式数据范围样例输入1样例输出1样例输入2样例输出2样例解释2Solution题目描述题目链接题目「天空度假山庄」中有一个\(n\)点\(m\)边的无向图,图中点......
  • 【小学期实训】附加题题解——最高段位
    [dp状态设计]实训附加题——最高段位目录[dp状态设计]实训附加题——最高段位题目描述背景题目输入格式输出格式数据范围样例输入1样例输出1样例输入2样例输出2样例解释2样例输入3样例输出3Solution题目描述题目链接背景香风智乃除了喜欢玩瓶中船之外,还喜欢打竞技游戏。有......
  • CF786E ALT 题解
    为什么你们第一眼都能想到最小割,我第一眼都只能想到费用流。为什么你们的做法都这么短,我一写就是\(5KB\)。费用流有一个基本矛盾,就是守卫只需拥有一只狗和每一个人都需要守卫有狗的基本矛盾。由于需求与供给不平衡,所以流量不好确定。如果有人费用流过了来长沙火车站,疯狂星期四......
  • [SDOI2010] 代码拍卖会 题解
    [SDOI2010]代码拍卖会题解题目描述一个\(n,n\le10^{18}\)位数,仅由\(1\sim9\)组成,后一位数字一定大于等于前一位数字。求这些数中可以被\(m,m\le500\)整除的有多少,对\(999911659\)取模。解析这个数一定形如\(112334455677788999\)可以把它拆成\[\begin{aligned}......
  • 黑群晖NAS7.0+安装问题解决经验分享
    感谢网上各种帖子及分享,为大家提供一个解决思路,机器配置多种多样,解决办法也仅供参考;1、引导后,无法找到群晖  遇到无法找到群晖的情况,首先要排除引导不兼容的问题。在bios中分别设置传统引导模式和UEFI引导模式尝试启动试下。最新版7.0.1的引导文件是两种启动方式都支持的,理......
  • 题解 [USACO18JAN] MooTube G
    题目链接可以发现,对于一个固定的\(k\),所有边权小于\(k\)的边对答案是没有贡献的,因为一条边的相关性是最小相关性,这也意味着我们不能从\(<k\)的边到达其他的点。由于本题有多组询问,所以对于没有用的边,将其看做被删除,有用的边,将其看做被插入。考虑到本题实际上要维护连通块......
  • 洛谷 P1122 最大子树和 题解
    一道入门的树形DP。首先我们对于数据进行有序化处理,这便于我们利用数据结构特点(可排序性)来发觉数据性质(有序、单调、子问题等等性质),以便于后续的转化、推理和处理。有序化可以“转化和创造”性质首先将视角从无根树切换为有根树,这样我们就可以得到一个带有最优子结构、无后效性......
  • HDU 5492 Find a path 题解
    Description在矩阵中,找一条到从\((1,1)\)到\((n,m)\)(只能向上,右走)的路径,使路径上方差最小。输出方差平方乘\(n+m-1\)的结果。对于所有数据,\(1\leqn,m,A_{i,j}\leq30\)。Solution设路径上的数为\(A_{1},A_{2},A_{3},\cdots,A_{n+m-1}\),\(\overline{A}\)为其平均数,则答......
  • 题解 序列合并
    题目链接首先不难想到,最小数的一定是\(a_1+b_1\),次小的数是\(a_1+b_2\)和\(a_2+b_1\)中小的。得出结论,若\(a_i+b_j\)是第\(k\)小,那么\(a_{i+1}+b_j\)和\(a_i+b_{j+1}\)有可能成为第\(k+1\)小。这是一个很优秀的性质,这意味着我们可以通过最小值推出次小值,再通过......