题目大意:
有一张桌子长度为n,第一个人是随便坐的,但是接下来坐的一个人,要尽可能的远离旁边的人,就是要求与最近距离的人靠得尽可能的远,问你长度为n的桌子能够坐的期望人数是多少?
思路:
通过推几个样例,我们可以发现当第一个人坐下以后,这张桌子能够坐总人数也已经可以知道了,那么我们就是要求
1
n
∗
∑
i
=
1
n
q
(
x
)
\frac {1}{n}*\sum_{i=1}^{n}q(x)
n1∗∑i=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(x−1)⌋)+f((x−1)−⌊2(x−1)⌋)+1,x = 1 || x = 2x ≥3
如下图:
我们假设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(x−1)⌋)和f((x−1)−⌊2(x−1)⌋)得到的,那么就是
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(x−1)⌋)+f((x−1)−⌊2(x−1)⌋)+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(x−1)+1,x ≤1x ≥2
根据题目意思,如果一端坐着人的话,那么下个人必定要坐另一端。那么我们就形成了一个两端都坐着人,空闲长度为x-1,其期望人数为
f
(
x
−
1
)
f(x-1)
f(x−1),那么
g
(
x
)
=
f
(
x
−
1
)
+
1
g(x)=f(x-1)+1
g(x)=f(x−1)+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=1∑x(g(x−i)+g(i−1)+1)
这个代表着我们选择一个起始位置i,选择好以后就会形成了两个一端坐着人,一端没有坐人的区间,那么
g
(
x
−
i
)
g(x-i)
g(x−i)代表着这个点到末尾的区间的期望人数,
g
(
i
−
1
)
g(i-1)
g(i−1)代表着这个点到桌子开头的区间的期望人数(这里我假设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=1∑x−1g(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;
}
道阻且长,且行且珍惜。