HDU 6305 RMQ Similar Sequence(笛卡尔树+线性求逆元+期望)

题目链接

RMQ Similar Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 255535/255535 K (Java/Others)
Total Submission(s): 999    Accepted Submission(s): 327

Problem Description

Chiaki has a sequence A={a1,a2,…,an}. Let RMQ(A,l,r) be the minimum i (l≤i≤r) such that ai is the maximum value in al,al+1,…,ar.

Two sequences A and B are called \textit{RMQ Similar}, if they have the same length n and for every 1≤l≤r≤n, RMQ(A,l,r)=RMQ(B,l,r).

For a given the sequence A={a1,a2,…,an}, define the weight of a sequence B={b1,b2,…,bn} be ∑i=1nbi (i.e. the sum of all elements in B) if sequence B and sequence A are RMQ Similar, or 0 otherwise. If each element of B is a real number chosen independently and uniformly at random between 0 and 1, find the expected weight of B.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤106) -- the length of the sequence.
The second line contains n integers a1,a2,…,an (1≤ai≤n) denoting the sequence.
It is guaranteed that the sum of all n does not exceed 3×106.

Output

For each test case, output the answer as a value of a rational number modulo 109+7.
Formally, it is guaranteed that under given constraints the probability is always a rational number pq (p and q are integer and coprime, q is positive), such that q is not divisible by 109+7. Output such integer a between 0 and 109+6 that p−aq is divisible by 109+7.

Sample Input

3

3

1 2 3

3

1 2 1

5

1 2 3 2 1

Sample Output

250000002

500000004

125000001

题意:

给你一个长度为n的A序列,定义了一种相似关系RMQ-similar——当对于任意的l,r,RMQ(A,l,r)=RMQ(B,l,r),则称A,B相似(这里的RMQ指的是[l,r]里面的最大值的下标,并且有多个最大值下取最小的下标)

现在B 都是[0,1]之间的实数,B也是长度为n的序列,定义序列B的权值是Σbi (i∈[1,n]),问你B与A相似的期望的权值是多少

解析:

先上大佬的题解

  • 考虑到B中的元素是实数,因此元素相同的概率为0。可以假设是一个排列。
  • [0,1]内随机一个实数的期望是1/2,那么一个排列的期望就是n/2。
  • 问题等价于:B为n的一个全排列,满足RMQ形态和AA相同的方案数s。那么答案就是\frac{s}{n!}*\frac{n}{2}
  • RMQ形态相同即两者的笛卡尔树形态相同。
  • 符合条件的数量就是B数组元素的全序数量,即树的拓扑序的数量s:\frac{n!}{\prod sizei}
  • 于是答案为:\frac{n}{2*\prod sizei} (sizei表示以i为根的子树的大小)

下面是解释概率的东西

首先在[0,1]里面取两个任意实数,这两个任意实数相等的概率为0=1/∞
那么对于一个n个数的排列,排列的数是任意从[0,1]取一个实数。
对于取一个数的期望1/2(因为[0,1]里面是均匀分布,从均匀分布的数学期望是(a+b)/2)
并且这里各个位置从[0,1]内取数是相互独立的,所以和的期望就是期望的和=n/2


1-n的全排列有n^2种情况,所以任意一个全排列的概率是1/(n!)
也可以这样理解,当取第一个数时,n个数种取一个数的概率时1/n,取第二个数时的概率时1/(n-1)......
所以1-n中的一个排列的概率是1/n!
然后假设满足与A相似的B的排列数量是s个,那么任意一个1-n的排列满足条件的概率是\frac{s}{n!}
最后答案就是n个位置取数的期望*排列满足条件的概率=\frac{s}{n!}*\frac{n}{2}

然后是笛卡尔树的讲解笛卡尔树
 

然后听了dls的讲解,发现上面的你不知道也没事,他直接把求满足条件的排列的概率如何计算讲出来了

也就是\frac{s}{n!}这一部分,所以至于树的拓扑序....至今也不知道是什么东西........。

简单概括dls说的满足条件的概率就是每一个位置要满足条件的概率就是1/(以该位置为根的笛卡尔树的子树的大小)

也就是上面那个\frac{1}{sizei},然后再把笛卡尔树的每一棵子树的概率乘起来,就是满足条件的排列的概率了。

 

#include <cstdio>
#include <cstring>
#include <utility>
#include <algorithm>
#define mp make_pair
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
using namespace std;
typedef pair<int ,int> PII;
typedef long long ll;
const int MAXN = 1e6+100;
const ll MOD =1e9+7;
int n;
int a[MAXN];
int l[MAXN],r[MAXN],vis[MAXN];
int stk[MAXN],top;
int size=1;
ll inv[MAXN];

ll dfs(int rt)
{
	if(l[rt]==0&&r[rt]==0) return 1;
	ll num=1;
	if(l[rt]) num+=dfs(l[rt]);
	if(r[rt]) num+=dfs(r[rt]);
	size=size*inv[num]%MOD;
	return num;
}


void build() {   //O(n)建笛卡尔树
	int top=0;
	rep(i,1,n+1) l[i]=0,r[i]=0,vis[i]=0;
	rep(i,1,n+1) {
		int k=top;
		while (k>0&&a[stk[k-1]]<a[i]) --k;
		if (k) r[stk[k-1]]=i;
		if (k<top) l[i]=stk[k];
		stk[k++]=i;
		top=k;
	}
	rep(i,1,n+1) vis[l[i]]=vis[r[i]]=1;
	int rt=0;
	rep(i,1,n+1) if (vis[i]==0) rt=i;  //找根
	dfs(rt);
}

int main()
{
	int t;
	inv[1]=1;
	rep(i,2,MAXN) inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;   //O(n)求逆元
	scanf("%d",&t);
	while (t--)
	{
		size=1;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			int tmp;
			scanf("%d",&tmp);
			a[i]=tmp;
		}
		build();
		printf("%lld\n",size*inv[2]%MOD*n%MOD);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/81233145