【XSY4074】intervcl C(推式子,根号分类)

题面

intervcl C

题解

首先询问和原数列顺序无关,那么不妨把数列从大到小排序,仍记为 \(a_i\)

那么题目就是给出 \([l,r]\),问 \(a_l,a_{l+1},\cdots,a_r\) 中任取 \(k\) 个数,这 \(k\) 个数中最大值的期望。

由于这是等概率选择,每种情况出现的概率为 \(\dfrac{1}{\binom{m}{k}}\)(记 \(m=r-l+1\)),所以我们只需计算每种情况的最大值之和即可。

容易想到直接枚举最大值为 \(a_i\),那么剩余的 \(k-1\) 个数就必须从 \(a_{i+1},a_{i+2},\cdots,a_r\) 里面选,方案数为 \(\dbinom{r-i}{k-1}\),故最大值为 \(a_i\) 的贡献为 \(a_i\times \dbinom{r-i}{k-1}\)

所以总和即为 \(\sum\limits_{i=l}^r \dbinom{r-i}{k-1}\times a_i\)

总时间复杂度 \(O(nq)\),上述部分都是比较容易想到的。

注意到 \(\sum k\leq 10^5\),考虑把单次询问从 \(O(n)\)\(O(k)\) 转换。

受到 subtask4 的启发,我们设 \(f_k[r]=\sum\limits_{i=1}^r\dbinom{r-i}{k-1}\times a_i\),那么每次询问 \([l,r]\) 的答案即为:

\[f_k[r]-\sum_{i=1}^{l-1}\dbinom{r-i}{k-1}\times a_i \]

试图也用 \(f\) 来表示 \(\sum\limits_{i=1}^{l-1}\dbinom{r-i}{k-1}\times a_i\)

\[\begin{aligned} &\sum_{i=1}^{l-1}\dbinom{r-i}{k-1}\times a_i\\ =&\sum_{i=1}^{l-1}\sum_{j=0}^{k-1}\dbinom{r-l+1}{j}\dbinom{l-1-i}{k-1-j}\times a_i \end{aligned} \]

(上面这步用到了范德蒙德卷积)

范德蒙德卷积:

\[\sum_{i=0}^{k}\dbinom{n}{i}\dbinom{m}{k-i}=\dbinom{n+m}{k} \]

证明:从组合意义上即可理解,相当于从各有 \(n\) 个和 \(m\) 个的两堆中共取出 \(k\) 个球。

继续推:

\[\begin{aligned} &\sum_{i=1}^{l-1}\dbinom{r-i}{k-1}\times a_i\\ =&\sum_{i=1}^{l-1}\sum_{j=0}^{k-1}\dbinom{r-l+1}{k-1-j}\dbinom{l-1-i}{j}\times a_i\\ =&\sum_{i=1}^{l-1}\sum_{j-1}^{k}\dbinom{r-l+1}{k-j}\dbinom{l-1-i}{j-1}\times a_i\\ =&\sum_{j-1}^{k}\dbinom{r-l+1}{k-j}\sum_{i=1}^{l-1}\dbinom{l-1-i}{j-1}\times a_i\\ =&\sum_{j-1}^{k}\dbinom{r-l+1}{k-j}f_{j}[l-1]\\ \end{aligned} \]

故每次询问 \([l,r]\) 的答案就是:

\[f_k[r]-\sum_{j-1}^{k}\dbinom{r-l+1}{k-j}f_{j}[l-1] \]

\(P=\sum k\),那么这样询问的总时间复杂度就是 \(O(q+P)\) 的了,但是如果暴力 \(O(kn^2)\) 预处理 \(f\) 的话我们是无法接受的。

考虑优化预处理的过程:

观察定义式 \(f_k[r]=\sum\limits_{i=1}^r\dbinom{r-i}{k-1}\times a_i\),由组合数递推公式 \(\dbinom{n}{m}=\dbinom{n-1}{m}+\dbinom{n-1}{m-1}\) 可知:

\[\begin{aligned} f_k[r]&=\sum\limits_{i=1}^r\dbinom{r-i}{k-1}\times a_i\\ &=\sum\limits_{i=1}^r\left[\dbinom{r-i-1}{k-1}+\dbinom{r-i-1}{k-2}\right]\times a_i\\ &=f_{k}[r-1]+f_{k-1}[r-1] \end{aligned} \]

于是预处理 \(f\) 的时间复杂度由 \(O(kn^2)\) 降到了 \(O(kn)\),但这样还是不够。

我们考虑设置一个阈值 \(B\)

  • \(k> B\) 时我们使用最开始说的暴力算法,这种算法的使用次数不会超过 \(\dfrac{P}{B}\),总时间复杂度 \(O(\dfrac{nP}{B})\)

  • \(k\leq B\) 时我们先 \(O(nB)\) 预处理出所有的 \(f_k[r]\),然后再 \(O(q+P)\) 询问。

总时间复杂度 \(O(nB+\dfrac{nP}{B})\),注意到 \(n,P\) 同阶,取 \(B=\sqrt P\) 时有最优的时间复杂度 \(O(n\sqrt n)\)

#include<bits/stdc++.h>

#define SN 320
#define N 100010

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int n,q,B,a[N],b[N];
int fac[N],ifac[N];
int f[SN][N];

int C(int n,int m)
{
	if(n<0||m<0||m>n) return 0;
	return mul(mul(fac[n],ifac[m]),ifac[n-m]);
}

int solve1(int l,int r,int k)
{
	int ans=0;
	for(int i=l;i<=r;i++)
		ans=add(ans,mul(C(r-i,k-1),a[i]));
	return ans;
}

int solve2(int l,int r,int k)
{
	int ans=f[k][r];
	for(int j=1;j<=k;j++)
		ans=dec(ans,mul(C(r-l+1,k-j),f[j][l-1]));
	return ans;
}

int main()
{
	n=read(),q=read(),B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) b[i]=a[i];
	reverse(a+1,a+n+1);
	fac[0]=1;
	for(int i=1;i<=100000;i++) fac[i]=mul(fac[i-1],i);
	ifac[100000]=poww(fac[100000],mod-2);
	for(int i=100000;i>=1;i--) ifac[i-1]=mul(ifac[i],i);
	for(int r=1;r<=n;r++) f[1][r]=add(f[1][r-1],a[r]);
	for(int k=2;k<=B;k++)
		for(int r=1;r<=n;r++)
			f[k][r]=add(f[k-1][r-1],f[k][r-1]);
	while(q--)
	{
		int l=read(),r=read(),k=read();
		l=lower_bound(b+1,b+n+1,l)-b;
		r=upper_bound(b+1,b+n+1,r)-b-1;
		swap(l,r);
		l=n-l+1,r=n-r+1;
		printf("%d ",r-l+1);
		if(k>r-l+1)
		{
			puts("-1");
			continue;
		}
		printf("%d\n",mul(k>B?solve1(l,r,k):solve2(l,r,k),poww(C(r-l+1,k),mod-2)));
	}
	return 0;
}
/*
7 3
83 74 100 89 95 79 72
90 100 3
80 89 1
70 79 2
*/
posted @ 2022-10-31 07:23  ez_lcw  阅读(16)  评论(0编辑  收藏  举报