hdu7048 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1005 Link with EQ

https://acm.hdu.edu.cn/showproblem.php?pid=7048

题意:

一张可以做n个人的桌子,第一个人随便找一个位置坐,后面的人找一个距离有人的最短距离最大的位置坐。

当一个人发现他必须要和某个人挨着坐时,这张桌子就满了。

问当桌子坐满的时候,期望做了多少个人

这是个线形的桌子,一直以为是圆桌。。。

第一个人位置确定后,这个桌子能坐多少人也定好了

设f[i]表示有连续的i+2个位置,两头都被坐了,还剩下中间i个空位,还能够坐的人数

g[i]表示有连续的i+1个位置,一头被坐了,还剩下i个空位,还能够坐的人数

h[i]表示有连续的i个位置能够坐的人数

f[i]:

若i是奇数,那么下一个人会坐最中间

若i是偶数,那么下一个人会坐中间2个中的某一个。无论坐哪个,分成的左右两部分是一样的

所以可以认为下一个人坐下之后,会把i分为 (i-1)/2 和 i-1-(i-1)/2 两部分

所以 f[i]=f [(i-1)/2]+f[i-1-(i-1)/2]+1,i>=3

当i<3时,f[i]=0

g[i]:

一头被坐了,下一个人必须坐距离它最远的位置,所以会坐到另一头

所以g[i]=f[i-1]+1,i>=2

当i<2时,g[i]=0

h[i]:

枚举第一个人坐在哪儿,设为x

这样他把桌子分为左右两边,两边都是坐了一头

h[i]=( ∑ g[x-1]+g[i-x]+1 ) / i ,x∈[1,i]

h[i]= 2*(∑ g[x] ) / i ,x ∈[0,i-1]

#include<bits/stdc++.h>

using namespace std;

#define N 1000001

const int mod=1e9+7;

int f[N],g[N],sg[N],inv[N];

int main()
{
    for(int i=3;i<N;++i) f[i]=(f[i-1>>1]+f[i-1-(i-1>>1)]+1)%mod;
    for(int i=2;i<N;++i) g[i]=f[i-1]+1;
    for(int i=2;i<N;++i) sg[i]=(sg[i-1]+g[i])%mod;
    inv[1]=1;
    for(int i=2;i<N;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    int T,n,ans;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        ans=(2ll*inv[n]*sg[n-1]%mod+1)%mod;
        printf("%d
",ans);
    }
}
作者:xxy
本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15230773.html