本题说是求概率,实际上由于
[
l
,
r
]
[l,r]
[l,r] 总数一定,要求的就是不合法的
[
l
,
r
]
[l,r]
[l,r] 的情况数
何时不合法?
首先我们会发现,只有 query 函数递归到叶子时,由于上面的 define,才可能导致 a a a 数组越界而 RE
注意这里为什么说 “可能” ,考虑下面这种情况
注意到达到
9
9
9 号点时,
l
s
=
18
,
r
s
=
19
ls = 18 , rs = 19
ls=18,rs=19 ,而
a
a
a 数组范围是
[
0
,
23
]
[0,23]
[0,23] ,所以没什么问题。但是到
12
,
13
12,13
12,13 号点就会错
考虑怎样的区间会访问到 12 , 13 12,13 12,13 这样的叶子
打表发现,当 RE 叶子 x x x ( x 代表原数组中表示的下标 ) 是一个左儿子时,当且仅当 l ≤ r = x l\leq r = x l≤r=x 的区间会访问到,共 x x x 个区间
右儿子时,则需要满足 x = l ≤ r x=l\leq r x=l≤r ,共 n − x + 1 n-x+1 n−x+1 个
那么问题很清晰了,直接在线段树上模拟这个过程,递归到叶子时如果发现这是一个 RE 叶子,根据左右情况累加到 a n s ans ans 里
需要注意的一点是:一个区间 如果左右端点都是 RE 叶子的话 会被重复算,容斥一下
一组数据 RE 的概率是 a n s n ( n + 1 ) / 2 \Large\frac{ans}{n(n+1)/2} n(n+1)/2ans ,那么 T 组数据全 AC 的概率就是 Π ( 1 − a n s i n i ( n i + 1 ) / 2 ) \large\Pi(1-\frac{ans_i}{n_i(n_i+1)/2}) Π(1−ni(ni+1)/2ansi)
#include<bits/stdc++.h>
using namespace std ;
#define int long long
typedef long long LL ;
const int N = 1e5 + 100 ;
const LL mod = 1e9 + 7 ;
/*性质:若访问到的越界叶子x是一个左儿子,则所有 [l,x] l<=x 为不合法的询问
若为右儿子,则所有 [x,r] r>=x 不合法
*/
LL ksm( LL a , LL b )
{
LL res = 1 , t = a % mod ;
while( b ) {
if( b&1 ) res = res * t % mod ;
b = b >> 1 ;
t = t * t % mod ;
}
return res ;
}
int T ;
int n , q ;
LL cnt , ans , R = 1 ;
void build( int p , int l , int r )
{
if( l == r ) {
if( p*2+1 >= 4*n ) { // 越界叶子
if( p&1 ) {
ans += n-l+1 ;
cnt ++ ;
}
else {/*左*/
ans += l-cnt ;
}
}
return ;
}
int mid = ( l + r ) >> 1 ;
build( p<<1 , l , mid ) ;
build( p<<1|1 , mid+1 , r ) ;
}
signed main()
{
scanf("%lld" , &T ) ;
while( T -- ) {
ans = cnt = 0 ;
scanf("%lld%lld" , &n , &q ) ;
build( 1 , 1 , n ) ;
LL tot = 1LL*n*(n+1)%mod ;
R = R * ksm( ((tot-2LL*ans)%mod+mod)%mod*ksm( tot , mod-2 )%mod , q ) % mod ;
}
printf("%lld" , R ) ;
return 0 ;
}