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的更多相关文章

  1. 【XSY2786】Mythological VI 数学

    题目描述 有\(1\sim n\)一共\(n\)个数.保证\(n\)为偶数. 你要把这\(2n\)个数两两配对,一共配成\(n\)对.每一对的权值是他们两个数的和. 你想要知道这\(n\)对里最大的权 ...

  2. 在docker容器中vi指令找不到

    在使用docker容器时,有时候里边没有安装vi,敲vi命令时提示说:vi: command not found,这个时候就需要安装vi,可是当你敲apt-get install vi命令时,提示: ...

  3. linux vi 命令大全

    进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后 ...

  4. Cygwin中解决vi编辑器方向键和Backspace键不好使、安装vim的方法

    修改.virc文件(如果没有就创建)vi .virc 添加以下内容set nocpset backspace=start,indent,eol 保存退出:wq 如果是vim就修改.vimrc文件. 由 ...

  5. vi(vim)键盘图及其基本命令

    进入vi vi filename                打开或新建文件,并将光标置于第一行首 vi +n filename           打开文件,并将光标置于第 n行首 vi + fi ...

  6. vi安装Vundle+YouCompleteMe+注释快捷'scrooloose/nerdcommenter'

    Vundle is short for Vim bundle and is a Vim plugin manager. 从git上下载vundle $ git clone https://github ...

  7. vi学习总结

    1.模式 命令行模式:光标的移动.内容删除移动复制操作 插入模式:文字输入,即编辑状态 底行模式:文件保存或退出vi,设置编辑环境 2.基本操作 vi myfile,输入vi 文件名,,则进入vi. ...

  8. vim(vi)常用操作及记忆方法

    vi(vim)可以说是linux中用得最多的工具了,不管你配置服务也好,写脚本也好,总会用到它.但是,vim作为一个“纯字符”模式下的工具,它的操作和WINDOWS中的文本编辑工具相比多少有些复杂.这 ...

  9. vim vi Ubuntu

    在vi编辑模式下按退格键不能删除内容,按方向键不能上下左右移动?如果是则:1. 在vi里非编辑模式下按冒号进入到末行命令模式,然后输入set nocompatible,回车,然后在进入vi编辑模式,看 ...

随机推荐

  1. [MIT Intro. to algo]Lecture 1: 课程介绍,算法优势,插入算法和归并算法分析,渐近符号

    The theoretical study of computer program performance and resource useage.   First, analysis and the ...

  2. Datawhale MySQL 训练营 Task4 表联结

    学习内容 MySQL别名 列别名,将查询或者筛选出来列用AS 命名,如果有空格则需要引号 '' SELECT xxx AS xxxx FROM WHERE GROUP BY HAVING 表别名, 把 ...

  3. python-gevent模块(自动切换io的协程)

    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import gevent     def foo() ...

  4. QT中的小细节

    一 .  QT4和QT5的区别(信号和槽):1.  QT4: connect(button,SIGNAL(pressed()),this,SLOT(close())); /** * 优点 :写法简单 ...

  5. MyForm_参考django的Form组建

    fork wupeiqi:https://github.com/fat39/Tyrion 组件说明:https://www.cnblogs.com/wupeiqi/p/5938916.html

  6. Mac SpotLight无法搜索

    在终端运行如下命令: sudo mdutil -i on /

  7. 2-Seventh Scrum Meeting20151207

    任务分配 闫昊: 今日完成:完成数据库设计. 明日任务:和唐彬讨论接口如何在android实现. 唐彬: 今日完成:读了IOS讨论区后台接口. 明日任务:和闫昊讨论接口如何在android实现. 史烨 ...

  8. 第三周vim入门学习2

    一.vim重复命令 1.重复执行上次命令 在普通模式下.(小数点)表示重复上一次的命令操作 拷贝测试文件到本地目录 $ cp /etc/protocols . 打开文件进行编辑 $ vim proto ...

  9. 20172324《Java程序设计》第二周学习总结

    20172324<Java程序设计>第2周学习总结 教材学习内容总结 了解了字符串及其拼接和转义序列的使用. Java的基本数据类型. 定义数据转换类型和实现其转换的方法. Scanner ...

  10. c# 程序重启设定

    问题情境: 程序随着时间运行,越来越大.暂时想到的两种方法,一是反攻代码,查看占内存大的函数,是不是没有回收.再就是暴力设定程序定时重启. 解决原理: 定时重启:暂设定timer,时间匹配执行rest ...