HDU7048 Link with EQ

题目链接

题目大意
  有一张桌子长度为n,第一个人是随便坐的,但是接下来坐的一个人,要尽可能的远离旁边的人,就是要求与最近距离的人靠得尽可能的远,问你长度为n的桌子能够坐的期望人数是多少?
思路:
  通过推几个样例,我们可以发现当第一个人坐下以后,这张桌子能够坐总人数也已经可以知道了,那么我们就是要求 1 n ∗ ∑ i = 1 n q ( x ) \frac {1}{n}*\sum_{i=1}^{n}q(x) n1i=1nq(x)( 1 n \frac{1}{n} n1为第一个人随机选择一个位置的概率,q(x)为选择x这个位置后,桌子能够坐的人数),现在的关键就是去求出 ∑ i = 1 n q ( x ) \sum_{i=1}^{n}q(x) i=1nq(x)的值是多少?
  我们可以定义一个 f ( x ) f(x) f(x)代表两端都坐着人然后这两个人之间的空闲距离为x能够坐的期望人数。
  那么我们就可以推导出
f ( x ) = { 0 , x = 1 || x = 2 f ( ⌊ ( x − 1 ) 2 ⌋ ) + f ( ( x − 1 ) − ⌊ ( x − 1 ) 2 ⌋ ) + 1 , x  ≥ 3 f(x)= \begin{cases} 0, & \text{x = 1 || x = 2} \\ f(\lfloor \frac{(x-1)}{2} \rfloor)+f((x-1)-\lfloor \frac{(x-1)}{2} \rfloor)+1, & \text{x $\ge$3} \end{cases} f(x)={0,f(2(x1))+f((x1)2(x1))+1,x = 1 || x = 23

如下图:
在这里插入图片描述
  我们假设1和10已经坐着人了,那么就是求 f ( 8 ) f(8) f(8)。解释: f ( x ) f(x) f(x)代表两端都坐着人然后这两个人之间的空闲距离为x能够坐的期望人数。1和10之间的空闲距离就是2到9,长度为8,就是 f ( 8 ) f(8) f(8).
  然后由于我们选择了1和10那么根据题目意思我们可以选择5或者6,这两个不管这么选都是一样的,那么我们这里选择5,那么这里又产生了两个两端都坐着人的区间 [ 1 , 5 ] [1,5] [1,5] [ 5 , 10 ] [5,10] [5,10],这两个区间分别代表 f ( 3 ) f(3) f(3) f ( 4 ) f(4) f(4),那么 f ( 8 ) = f ( 3 ) + f ( 4 ) + 1 f(8)=f(3)+f(4)+1 f(8)=f(3)+f(4)+1(这里加1是因为你5这个位置坐了一个人所以要加1),多推几个,那么我们就可以知道每一个 f ( x ) f(x) f(x)都是由其 f ( ⌊ ( x − 1 ) 2 ⌋ ) 和 f ( ( x − 1 ) − ⌊ ( x − 1 ) 2 ⌋ ) f(\lfloor \frac{(x-1)}{2} \rfloor)和f((x-1)-\lfloor \frac{(x-1)}{2} \rfloor) f(2(x1))f((x1)2(x1))得到的,那么就是 f ( x ) = f ( ⌊ ( x − 1 ) 2 ⌋ ) + f ( ( x − 1 ) − ⌊ ( x − 1 ) 2 ⌋ ) + 1 f(x)=f(\lfloor \frac{(x-1)}{2} \rfloor)+f((x-1)-\lfloor \frac{(x-1)}{2} \rfloor)+1 f(x)=f(2(x1))+f((x1)2(x1))+1
  然后我们再定义一个函数 g ( x ) g(x) g(x)为其中一边坐着人,然后另一边没有人坐,空闲长度为x的能够坐的期望人数。
  那么我们就可以推导出
g ( x ) = { 0 , x  ≤ 1 f ( x − 1 ) + 1 , x  ≥ 2 g(x)= \begin{cases} 0, & \text{x $\leq$1} \\ f(x-1)+1, & \text{x $\ge$2} \end{cases} g(x)={0,f(x1)+1,12
  根据题目意思,如果一端坐着人的话,那么下个人必定要坐另一端。那么我们就形成了一个两端都坐着人,空闲长度为x-1,其期望人数为 f ( x − 1 ) f(x-1) f(x1),那么 g ( x ) = f ( x − 1 ) + 1 g(x)=f(x-1)+1 g(x)=f(x1)+1(另一端坐人加1)。
  最后我们再定一个 h ( x ) h(x) h(x)代表长度为x能够坐的期望人数。那么
h ( x ) = 1 x ∑ i = 1 x ( g ( x − i ) + g ( i − 1 ) + 1 ) h(x)=\frac{1}{x}\sum_{i=1}^x(g(x-i)+g(i-1)+1) h(x)=x1i=1x(g(xi)+g(i1)+1)
  这个代表着我们选择一个起始位置i,选择好以后就会形成了两个一端坐着人,一端没有坐人的区间,那么 g ( x − i ) g(x-i) g(xi)代表着这个点到末尾的区间的期望人数, g ( i − 1 ) g(i-1) g(i1)代表着这个点到桌子开头的区间的期望人数(这里我假设1号座位为开头,x号座位为结尾),+1是因为我起始位置坐人要加1.
   h ( x ) h(x) h(x)化简后:
h ( x ) = 1 + 2 x ∑ i = 1 x − 1 g ( i ) h(x)=1+\frac{2}{x} \sum_{i=1}^{x-1}g(i) h(x)=1+x2i=1x1g(i)
  那么我们就可以预处理出 f ( x ) , g ( x ) , s u m g ( x ) f(x),g(x),sumg(x) f(x),g(x),sumg(x),然后求出长度为n所能做的期望人数了。

代码如下:

#include<bits/stdc++.h>
#define Case int t;scanf("%d",&t);while(t--)
using namespace std;
typedef long long ll;
const int N=1e6+10;
const long double eps=1e-20;
const int mod=1e9+7;
ll a[N];ll f[N];
ll g[N],sumg[N];
ll qpow(ll q,ll n){
	ll res=1;
	while(n){
		if(n&1)res=(res*q)%mod;
		n>>=1;
		q=(q*q)%mod;
	}
	return res;
}
void run(){
	ll n;
	scanf("%lld",&n);
	ll sum=(1ll+2*qpow(n,mod-2)%mod*sumg[n-1]%mod)%mod;
	printf("%lld\n",sum);
}
int main(){
	#ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
    #endif
	f[1]=0;
	f[2]=0;
	for(int i=3;i<N;i++){
		int d=(i-1)/2;
		f[i]=(f[d]+f[(i-1)-d]+1)%mod;
	}
	g[0]=0;
	g[1]=0;
	for(int i=2;i<N;i++){
		g[i]=(f[i-1]+1)%mod;
	}
	sumg[0]=0;
	for(int i=1;i<N;i++){
		sumg[i]=(sumg[i-1]+g[i])%mod;
	}
    Case
	run();
    return 0;
}

道阻且长,且行且珍惜。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值