ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1295F Good Contest

2022-07-31 18:34:14  阅读:238  来源: 互联网

标签:Good return power Contest int ll 区间 CF1295F mod


written on 2022-05-06

写了三天了,写篇题解加深一下印象。

首先分析题意。我们发现最后的概率是以 分子乘以分母逆元的形式 出现的,然后这又是一道概率题。那么我们就可以考虑直接算满足的方案数了,因为最后的总方案数十分好算,就是所有长度相乘。

题目的限制是单调不增,直观的想法是用 \(f_{i,j}\) 记录第 \(i\) 个区间选数为 \(j\) 的情况,转移很显然。但是一看数据 \(0≤l i≤r i≤998244351\) ,直接作废。

考虑优化,观察到 \(n\) 的范围很小,一般的想法是不是直接对这些区间进行离散化?没错,离散化之后的区间被分成了一小段一小段,而且最多只有 \(2n\) 个,这给我们的启示就是,可不可以通过这些段来转移?

答案是肯定的,我们记 \(f_{i,j}\) 为选到 \(i\) 个位置,此时选择第 \(j\) 个小区间的总方案数。注意,此时我们不能直接由 \(i-1\) 转移而来,因为即使在同一小区间内也不能满足 \(a_i \ge a_i-1\) ,所以转移的时候,我们应当一段数一起转移,这样的话,利用插板法,我们就可以巧妙地规避这样的问题。

插板法: \(n\) 个箱子塞 \(m\) 个相同小球的方案数为\(\dbinom{n+m-1}{n}\) .

那么转移就显然了。要注意的一点是对于一个枚举的 \(k\) ,它必须要包含所在的这个小区间才行,否则就要直接跳出循环。

最后满足条件的方案数就是 \(\sum_{i=1}^{cnt} f_{n,i}\) ,再乘以总方案逆元即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
ll power(ll a,ll b)
{
	if(!b) return 1ll;
	if(b&1) return a*power(a,b-1)%mod;
	ll res=power(a,b>>1)%mod;
	return res*res%mod;
}
ll inv(ll a){return power(a,mod-2);}
ll C(int a,int b)
{
	if(b>a/2) b=a-b;
	ll res=1;
	for(int i=1;i<=b;i++) res=res*1ll*(a-i+1)%mod*inv(1ll*i)%mod;//边乘边除
	return res;
}
int n,l[55],r[55];
int tot,tmp[105];
ll f[55][105];
int main()
{
	scanf("%d",&n);
	ll fm=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&l[i],&r[i]);
		fm=fm*1ll*(r[i]-l[i]+1)%mod;
		tmp[++tot]=l[i],tmp[++tot]=++r[i];
	}
	sort(tmp+1,tmp+1+tot);
	int cnt=unique(tmp+1,tmp+1+tot)-tmp-1;
	for(int i=1;i<=n;i++) l[i]=lower_bound(tmp+1,tmp+1+cnt,l[i])-tmp,r[i]=lower_bound(tmp+1,tmp+1+cnt,r[i])-tmp;
	for(int i=1;i<=cnt;i++) f[0][i]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=l[i];j<r[i];j++)
		{
			int len=tmp[j+1]-tmp[j];
			for(int k=i-1;k>=0;k--)
			{
				if(l[k+1]>j||r[k+1]<=j) break;//所以只要有一个不满足(区间不包含j这个区间)就不继续累加 
				//小于等于是因为r是加一后的值(r<j就退出) 
				f[i][j]=(f[i][j]+f[i-1][j+1]*C(len+i-k-1,i-k)%mod)%mod;//因为在上面的k~i这部分都选编号为j的这个区间
				//n个箱子塞m个相同小球的方案数为C(n+m-1,n); 
			}
		}
		for(int j=cnt-1;j>=1;j--) f[i][j]=(f[i][j]+f[i][j+1])%mod;
	}
/*	for(int i=1;i<=n;i++) printf("l=%d r=%d\n",l[i],r[i]);
	for(int i=1;i<=n;i++) for(int j=1;j<=cnt;j++) printf("i=%d j=%d val=%lld\n",i,j,f[i][j]);*/
	//fz  f[n][1]
	printf("%lld",f[n][1]*inv(fm)%mod);
}

标签:Good,return,power,Contest,int,ll,区间,CF1295F,mod
来源: https://www.cnblogs.com/Freshair-qprt/p/16537757.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有