链接:https://ac.nowcoder.com/acm/contest/9692/F
来源:牛客网
现在有n堆石子,每堆石子初始大小为1。现在,猪猪会进行n-1轮操作,每次随机将任意相邻的两堆石子合并,合并的体力消耗是两堆石子大小之和
怎么说呢,被题解秀到了,自己瞎蒙了个规律推没了。
我首先考虑的是从末状态往前推,比如5的时候,
1 1 1 1 1
最终结果是 12 13 或14
然后总方案数是4!=24
瞎推了一下以为就是8×12+10×13+12×14
以后后面都是这样的然后第六个就不对了。
其实对于一次合并,这个和都是可以求得的,比如第一次合并的和一定为(n-1)! *2*n/n,第二次合并就是(n-1)!*2*n/(n-1),其实这就是一个期望和,而且可以约得出,所以直接求解就行了,不过这题还有dp的解法,蒻蒻没推出来~
但这类的期望题的思路真的很优秀!
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
typedef long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
#define per(i,j,n) for(ll i=j;i>=n;i--)
typedef unsigned long long ull;
typedef unsigned short us;
const ll INF= 1e17+7;
const ll maxx = 1e6+500;
const double eps=1e-8;
inline bool read(ll &num){char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,k;
const ll mod=1000000007;
vector<ll>v[maxx];
ll vis[maxx];
ll a,b;
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
ll t;
cin>>n;
if(n==1) printf("%lld\n",0);
if(n>=2)
{
ll ans=0;
rep(i,2,n)
{
ans+=qpow(i,mod-2);
ans%=mod;
}
ans=ans*2*n%mod;
rep(i,2,n-1) ans=ans*i%mod;
printf("%lld\n",ans);
}
return 0;
}