P3643 [APIO2016] 划艇

题意#

给你两个序列 a,b,求严格递增的序列 c 的个数,满足:i,ci[ai,bi]。特别的,如果 ci=0 则无视当前这个 ci

Solution#

好困难的 dp,耗我半个晚上。

首先是对区间离散化,然后转化成一堆区间。此时对 dp 的定义是:dpi,j 表示在考虑第 i 个学校的时候,这个学校派出了在第 j 个区间内的划艇数。

然后考虑此前每个学校可能的贡献。我们枚举有多少学校也是在区间 j 内的,假设是 p+1i 都在,然后枚举 p 所在的区间,假设为 k。不难发现,在 [p+1,i] 内的学校,如果有 m 所能在区间 j 内,那么这个区间内的方案数是:

(m+Lj1m)

因为在 Lj 个盒子中放 m 个球,每个盒子限放一个,有球可以不放。我们可以加 m 个盒子,然后任取 m 个放入球,再拿走这 m 个盒子。由于我们当前枚举的必须放,所以要减一。

这样我们就有:

dpi,j=p<ik<j(m+Lj1m)dpp,k

然后考虑优化这个东西。我们还是可以枚举 p,然后维护 m,把 k 前缀优化掉。还是容易做到的。令:

prei,j=kjdpi,k

那么转移就成了:

dpi,j=p<i(m+Lj1m)prep,j1

组合数就边求边推好了:

(m+Lj1m)=(m1+Lj1m1)×m+Lj1m

复杂度是 O(n3)

Code#

// Problem: 
//     P3643 [APIO2016] 划艇
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3643
// Memory Limit: 125 MB
// Time Limit: 3000 ms

#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
#define pb emplace_back
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define all(a) a.begin(),a.end()
#define siz(a) (int)a.size()
#define clr(a) memset(a,0,sizeof(a))
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define pt(a) cerr<<#a<<'='<<a<<' '
#define pts(a) cerr<<#a<<'='<<a<<'\n'
#define int long long
using namespace std;
const int MAXN=510;
const int MOD=1e9+7;
int inv[MAXN],a[MAXN],b[MAXN];
int dp[MAXN][MAXN<<1],pre[MAXN][MAXN<<1];
vector<int> lsh;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	inv[1]=1;rep(i,2,MAXN-10) inv[i]=((MOD-MOD/i)*inv[MOD%i]%MOD)%MOD;
	int n;cin>>n;
	rep(i,1,n) cin>>a[i]>>b[i],b[i]++,lsh.pb(a[i]),lsh.pb(b[i]);
	sort(all(lsh));lsh.erase(unique(all(lsh)),lsh.end());
	
	rep(i,0,siz(lsh)-1) pre[0][i]=1;
	rep(i,1,n) rep(j,1,siz(lsh)-1){
		if(a[i]<=lsh[j-1]&&b[i]>=lsh[j]){
			int L=lsh[j]-lsh[j-1],C=L,m=1;
			per(p,i-1,0){
				(dp[i][j]+=C*pre[p][j-1]%MOD)%=MOD;
				if(a[p]<=lsh[j-1]&&b[p]>=lsh[j])
					m++,C=C*(m+L-1)%MOD*inv[m]%MOD;
			}
		}pre[i][j]=(pre[i][j-1]+dp[i][j])%MOD;
	}
	int ans=0;
	rep(i,1,n) ans=(ans+pre[i][siz(lsh)-1])%MOD;
	cout<<ans<<'\n';
	return 0;
}
posted @   ZCETHAN  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示
主题色彩