题目链接
题目思路
这个(dp)有点巧妙
(dp[i][1])表示i个空位有一段被占领最终能有多少个人
(dp[i][2])表示i个空位有两端被占领最终能有多少个人
然后枚举端点,前缀和即可
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n;
ll dp[maxn][3];
ll pre[maxn];
ll qpow(ll a,ll b){
ll ans=1,base=a;
while(b){
if(b&1) ans=ans*base%mod;
base=base*base%mod;
b=b>>1;
}
return ans;
}
signed main(){
// dp[i][1] 表示i个空位有一段被占领
// dp[i][2] 表示i个空位有两端被占领
for(int i=2;i<=1e6;i++){
if(i>2){
dp[i][2]=(dp[i/2][2]+dp[i-i/2-1][2]+1)%mod;
}
dp[i][1]=dp[i-1][2]+1;
pre[i]=(pre[i-1]+dp[i][1])%mod;
}
int _; scanf("%d",&_);
while(_--){
scanf("%d",&n);
ll ans=(2*pre[n-1]+n)*qpow(n,mod-2)%mod;
printf("%lld
",ans);
}
return 0;
}