AGC 032 F 简要题解
太神了这题。。。
首先游戏可以直接等价成每次插入三类边(各120度),然后最后我们可以直接当成在第一个的一个1/3扇形里面找一段最小的段左右颜色不同。
这里可以直接dp出有多少段颜色不同的方案,然后易得 i 段的期望长度和是i/n(每段等价)。
然后我们需要找k段分一个长度len最小长度的期望。
这个期望是len/(k^2)。
证明是(此处认为len=1)考虑最小长度大于等于i的概率就是(1-k*i)^(n-1) 然后我们把这玩意求积分就行了。具体可以上知乎
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
inline int inv(int x){return qpow(x,mod-2);}
/* math */
int n;
const int N=2e6+5;
int fac[N],ifac[N];
inline void init(int n){
fac[0]=ifac[0]=1;for(int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
ifac[n]=inv(fac[n]);for(int i=n-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
int f[N][3];
int F(int x){
return f[x][1];
}
int G(int x){
return mul(inv(3),mul(inv(n),inv(x)));
}
int binom(int a,int b){
if(b>a)return 0;
return mul(fac[a],mul(ifac[b],ifac[a-b]));
}
int main()
{
cin >> n;
init(n*2);
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<3;j++)for(int k=0;k<3;k++)if(j!=k)f[i][j] = add(f[i][j], f[i-1][k]);
}
int ans=0,all= inv(qpow(3,n-1));
for(int i=1;i<=n;i++){
int P = mul(mul(F(i), binom(n,i)), all);
int L = G(i);
ans = add(ans, mul(P, L));
}
cout << ans << endl;
}