P3643 [APIO2016]划艇

P3643 [APIO2016]划艇

题意

一个合法序列可表示为一个长度为 n 的序列,其中第 i 个数可以为 0 或 [li,ri] 中一个整数,且满足所有不为零的数组成的子序列严格上升。求合法序列方案数。

思路

朴素动态规划做法为,设 fij 表示第 i 个数不为零且数量为 j 的方案数,则

ans=i=1nj=lirifijfij=k=1j1q=0i1fqk,j[li,ri]

但是第二维枚举太多。考虑优化。

首先,我们考虑一段区间,按照上面的方式递推需要依次枚举数量再枚举 i1 个数的方案进行转移,不能够简化的主要原因是因为每个数都有一个限定的区间。若不加限定,发现这段转移可以简化为一个简单问题:每个数可以选取值范围内任意的值或 0,求所有不为零的数组成的子序列严格上升方案数。设取值区间大小为 len,数的数量为 n,则答案为 (len+nn)。可以理解为额外增加 n 个 0 表示选 0。

所以我们进行离散化,将取值范围分为若干段,每个数的范围由若干这样的段组成。对于每一段我们都可以按照上面的方法转移。即对于这一段区间 j,对于所有包含它的数字,可以从 0i1 中任意一种状态 k 转移得到,并且需要乘上在 ki 中选任意个区间包含 j 的数字不为 0 的方案数,即 (len+m1m) 其中 m 为上述数的个数,len 为第 j 段的长度,减 1 是因为第 i 个必选。即

ans=i=1nj=lirifijfij=q=0i1(len+mjq1mjq)k=1j1fqk,j[li,ri],mjq=o=q+1i[j[lo,ro]],lenj

发现后面的求和维护一个前缀和即可。总时间复杂度 O(n3)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=505,mod=1e9+7;
	int n,m,l[maxn],r[maxn],b[maxn<<1],C[maxn],inv[maxn],f[maxn],ans;
	inline void work(){
		n=read();
		inv[1]=1;for(int i=2;i<=n;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		for(int i=1;i<=n;i++) l[i]=b[(i<<1)-1]=read(),r[i]=b[i<<1]=read(),b[i<<1]++;
		sort(b+1,b+1+(n<<1));
		m=unique(b+1,b+1+(n<<1))-b-1;
		for(int i=1;i<=n;i++) l[i]=lower_bound(b+1,b+1+m,l[i])-b,r[i]=lower_bound(b+1,b+1+m,r[i]+1)-b;
		C[0]=f[0]=1;
		for(int j=1;j<m;j++){
			int len=b[j+1]-b[j];
			for(int i=1;i<=n;i++) C[i]=1ll*C[i-1]*(len+i-1)%mod*inv[i]%mod;
			for(int i=n;i;i--) if(l[i]<=j and r[i]>=j+1){
				int cnt=1;
				for(int k=i-1;~k;k--) f[i]=(f[i]+1ll*C[cnt]*f[k])%mod,cnt+=l[k]<=j and r[k]>=j+1;
			}
		}
		for(int i=1;i<=n;i++) ans=(ans+f[i])%mod;
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}
posted @   Star_Cried  阅读(57)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示