大致题意:给你一个串A,定义RMQ相似串为,对任意区间[L,R],两个串RMQ所在位置相同。告诉你B串中每个元素服从于[0,1]上相互独立的均匀分布。B的权值定义为,当B与A串RMQ相似时,权值为所有元素之和,否则为0。现在问你B串的期望权值是多少。
串A可以看做n个数对,这n个数对之间有偏序,可以看做一个排列,B中两个数相等的几率为0,也可以看做一个数列。
发现这就是要求这两个数列构造出的笛卡尔树一样()。
又因为笛卡尔树满足点P的权值大于等于其子树内的所有值,
发现和拓扑序有点像,
树的拓扑序满足点P的拓扑序大于等于其子树内的所有点的拓扑序,
笛卡尔树的拓扑序列个数等于能构造出该笛卡尔树的序列个数!
又因为每个排列中数的和的期望为点数/2,算乘积就行。
树的拓扑序列个数怎么算,可以看我的另一篇博客:树的拓扑序列
AC code:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define mod 1000000007
#define LL long long
using namespace std;
int sum(LL n){ return 1ll * n % mod * ((n+1) % mod) % mod * ((mod+1)/2) % mod; }
template<class T>inline void read(T &res)
{
char ch;
for(;!isdigit(ch=getchar()););
for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0');
}
int main()
{
LL n,m;
int T;
read(T);
for(;T--;)
{
read(n);
n--;
m=0;
for(int i=60;i>=0;i--)
if(n>=(1ll << i+1) - 1)
{
n-=(1ll << i+1) - 1;
m+=1ll << i;
}
int ans=1;
if(n) ans=(ans + 1ll * n % mod * ((m+1) % mod) % mod);
for(int tmp=1;m;m>>=1,tmp=1ll * tmp * 2 % mod)
ans = (1ll * sum(m) * tmp + ans) % mod;
printf("%d\n",ans);
}
}