Mythological VI

Description

\(1...n\)一共\(n\)个数。保证\(n\)为偶数。
小M要把这\(n\)个数两两配对, 一共配成\(n/2\)对。每一对的权值是他们两个数的和。
小M想要知道这\(n\)对里最大的权值的期望是多少。可怜的小M当然不知道啦,所以她向你求助。
请输出答案对\(10^9+7\)取模的值。
  

Input

一行一个正整数,表示\(n\)
  

Output

一行一个整数,表示答案对\(10^9+7\)取模的值。
  

Sample Input

4

  

Sample Output

6

  

HINT

对于20%的数据, \(n\leq 10\)
对于40%的数据, \(n\leq 2*10^3\)
对于100%的数据, \(n\leq 5*10^5\)
  
    
    
  

Solution

  
​  首先可能的最大值最大为\(n+(n-1)=2n-1\)
  
​  考虑能不能枚举最大值\(v\),算出最大值等于每个\(v\)时的方案数,除以总方案数得到概率,再算出期望。
  
​  观察得出\(v\in [n+1,2n-1]\),所以只要在这个区间内枚举即可。
  
​  可是考虑到计算最大值恰好等于\(v\)的方案数不是很可行,于是我们看看能不能转化成先求前缀和:\(g[i]\)表示最大值小于等于\(v\)的方案数是多少。自然地,最大值等于\(v\)时的方案数为\(g_v-g_{v-1}\)
  
​  下面看怎么求\(g_v\),记\(a=\lfloor \frac v 2 \rfloor\)
  
​  首先这\(n\)个数中,有些比较特别:\((a,n]\)这些数,必须选择位于\([1,a]\)中的数,否则最大值可能超过\(v\)。那就先考虑这些数的匹配方法。
  
​  先看看\(n\)有多少种选法:\(n\)必须和\([1,v-n]\)中的数匹配,共\(v-n\)种选择。
 
​  \(n-1\)呢?必须和\([1,v-(n-1)]\)中的数匹配,共\(v-n+1\)种选择;但是\(n\)已经从\([1,v-n]\)挑走了一个数,所以总选择方案减1,仍然是\(v-n\)种选择。
   
​  由此从大到小考虑\((a,n]\),发现每个数的可选择方案都是\(v-n\),那么为\((x,n]\)\(n-a\)个数选择好匹配的总方案数为\((v-n)^{n-a}\)
  
​  此时\([1,a]\)个数中已有\(n-a\)个数被挑走做匹配了,剩下\(a-(n-a)=2a-n\)个数,由于它们都小于等于\(a\),所以剩下的数可以任意匹配而不会出现一对数权值之和大于\(v\)的情况。
  
​  记\(f(x)\)表示\(x\)个点任意两两匹配的方案数,推一推就得知\(f(x)=f(x-2)*(x-1)\),意思就是一个点从其他\(x-1\)个点挑一个,移除这两个点后继续操作。
  
​  则剩下的数的方案为\(f(2a-n)\)
  
  所以\(g_v=(v-n)^{n-a}*f(2a-n)\)
  
​  总方案数是多少?可以理解为\(g_{2n}\),也可以理解为\(f(n)\),总之就是完全没有限制时的方案数。
  
​  有了\(g\)数组,就可以算出对于最大值为\([n+1,2n-1]\)时的方案数,除以总方案数算出每个最大值出现的概率,最后就可以算出期望了。
    
  

#include <cstdio>
using namespace std;
const int mod=1e9+7;
const int N=500010;
int n,f[N*2],g[N*2];
inline int pow(int x,int y){
    int res=1;
    for(;y;x=1LL*x*x%mod,y>>=1)
        if(y&1) res=1LL*res*x%mod;
    return res;
}
int main(){
    scanf("%d",&n);
    f[0]=1;
    for(int i=2;i<=n;i+=2) f[i]=1LL*f[i-2]*(i-1)%mod;
    for(int v=n+1;v<=n*2;v++)
        g[v]=1LL*pow(v-n,n-v/2)*f[v/2-(n-v/2)]%mod;
    int ans=0;
    for(int v=n+1;v<=n*2;v++)
        (ans=ans+1LL*(g[v]-g[v-1])*v%mod)%=mod;
    ans=1LL*ans*pow(g[n*2],mod-2)%mod;
    printf("%d\n",ans<0?ans+mod:ans);
    return 0;
}

转载于:https://www.cnblogs.com/RogerDTZ/p/8641362.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值