5928. 【NOIP2018模拟10.26】苹果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huangjingyuan107/article/details/83479317

题目

对区间 [ 1 , 2 n ] [1,2^n] 建线段树。线段树中每个区间都有它自己的深度。
众所周知, 一个区间 [ L , R ] [L,R] 可以拆成log个区间。
S ( L , R ) S(L,R) 的期望。
对于一个区间 [ L , R ] [L,R] S ( L , R ) S(L,R) 表示 l o g log 个区间中包含L的那个区间的深度+ l o g log 个区间中包含R的那个区间的深度。如果只有1个区间,那么那个区间的深度算2次。

正解

40分:式子很容易就写出来了。
A n s = 1 C 2 n 2 i = 1 n d e p [ i ] ( s i z e [ i   x o r   1 ] ) + [ d e p [ i ] ( 2 n R [ i ] + 1 ) ] [ i ] + [ d e p [ i ] ( s i z e [ i   x o r   1 ] ) + d e p [ i ] L [ i ] ] [ i ] Ans=\frac{1}{C_{2^n}^2}\sum_{i=1}^n dep[i]*(size[i\ xor\ 1])+[dep[i]*(2^n-R[i]+1)]*[i为奇数]+[dep[i]*(size[i\ xor\ 1])+dep[i]*L[i]]*[i为偶数]
100分:找规律。或者优化40分的式子。
找规律:对于所有的 [ L , R ] [L,R] 数出每个区间遍历的次数。
可以得出结论:深度为i的区间总共被遍历了 2 i 1 ( 2 n + 2 ) 2^{i-1}(2^n+2) 次。
所以 A n s = i = 1 n i 2 i 1 ( 2 n + 2 ) = i = 1 n i 2 i ( 2 n 1 + 1 ) Ans=\sum_{i=1}^n i*2^{i-1}(2^n+2)=\sum_{i=1}^n i*2^i(2^{n-1}+1)
一个等差比数列。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
#define mo 1000000007
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
LL ans,w,w1;
LL m1,m2,m3,n;
LL calc(LL x){return (x*(x+1)%mo)*500000004%mo;}
LL ksm(LL x,LL y){
	LL rs=1;
	for(;y;y>>=1,x=(x*x)%mo)if(y&1)rs=(rs*x)%mo;
	return rs;
}
int main(){
	scanf("%lld",&n);
	m1=ksm(2,n-1);
	m2=m1*2%mo;
	m3=m2*2%mo;
	ans=(ans+(n%mo)*m3%mo-2+mo)%mo;
	w1=(4*(m1-1))%mo;
	ans=(ans-w1+mo)%mo;
	w1=(m1+1)%mo;
	ans=(ans*w1)%mo;
	w=calc(m2);
	ans=(ans*ksm(w,mo-2))%mo;
	printf("%lld",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huangjingyuan107/article/details/83479317
今日推荐