Mythological VI

Posted RogerDTZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于Mythological VI的主要内容,如果未能解决你的问题,请参考以下文章

DTOJ #3194. 去月球

尝试使用片段保存夜间模式状态

有没有办法以编程方式使用kotlin更改片段中的文本颜色?

如何使用 tabLayout 在 ViewPager 中显示片段?

使用 ViewPager 滑动时,片段没有调用 OnResume()

在片段中,如何停止 ZXing Scanner 的摄像头?