一、题目
二、解法
这道题必须要考虑到终止状态,由于题目给的是 0 / 1 0/1 0/1串,所以最后的状态一定是前面都是 0 0 0,后面全是 1 1 1。设 m m m为 0 0 0的个数, d p [ i ] dp[i] dp[i]表示前 m m m个数中有 i i i个数是 0 0 0的概率,从 d p [ i ] dp[i] dp[i]转移出去:
- 增加一个 0 0 0,从前面选一个 1 1 1,后面选一个 0 0 0: d p [ i ] × ( m − i ) 2 dp[i]\times(m-i)^2 dp[i]×(m−i)2
- 减少一个 0 0 0,从前面选一个 0 0 0,后面选一个 1 1 1: d p [ i ] × i × ( n − 2 m + i ) dp[i]\times i\times(n-2m+i) dp[i]×i×(n−2m+i)
- 不增不减,只选前 / / /后,选前后 1 / 0 1/0 1/0: C ( m , 2 ) + C ( n − m , 2 ) + i ( m − i ) + ( m − i ) ( n − 2 m + i ) C(m,2)+C(n-m,2)+i(m-i)+(m-i)(n-2m+i) C(m,2)+C(n−m,2)+i(m−i)+(m−i)(n−2m+i)
k k k很大,但我们可以做矩阵加速,注意设置矩阵的时候是从 i + 1 / i − 1 i+1/i-1 i+1/i−1转移到 i i i,所以要把上文的 i i i替换成 i + 1 / i − 1 i+1/i-1 i+1/i−1,具体可以参考代码。
#include <cstdio>
#include <cstring>
const int M = 105;
const int MOD = 1e9+7;
#define int long long
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,k,t,t1,t2,a[M];
struct Matrix
{
int n,m,a[M][M];
Matrix() {n=m=0;memset(a,0,sizeof a);}
void clear() {memset(a,0,sizeof a);}
Matrix operator * (const Matrix &b) const
{
Matrix r;
r.n=n;r.m=b.m;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=b.m;k++)
r.a[i][k]=(r.a[i][k]+a[i][j]*b.a[j][k])%MOD;
return r;
}
void print()
{
for(int i=1;i<=n;i++,puts(""))
for(int j=1;j<=m;j++)
printf("%lld ",a[i][j]);
}
}A,F;
Matrix qkpow(Matrix a,int b)
{
Matrix r;
r.n=r.m=a.n;
for(int i=1;i<=a.n;i++)
r.a[i][i]=1;
while(b>0)
{
if(b&1) r=r*a;
a=a*a;
b>>=1;
}
return r;
}
int fast(int a,int b)
{
int r=1;
while(b>0)
{
if(b&1) r=r*a%MOD;
a=a*a%MOD;
b>>=1;
}
return r;
}
signed main()
{
n=read();k=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
if(!a[i]) m++;
}
for(int i=1;i<=m;i++)
if(!a[i]) t++;
A.n=A.m=F.n=m;F.m=1;
if(m==0 || m==n)
{
puts("1");
return 0;
}
t1=m*(m-1)/2;t2=(n-m)*(n-m-1)/2;
int inv=fast(n*(n-1)/2,MOD-2);
for(int i=0;i<=m;i++)
{
if(i>0) A.a[i][i-1]=(m-(i-1))*(m-(i-1));
A.a[i][i]=t1+t2+i*(m-i)+(m-i)*(n-2*m+i);
if(i<m) A.a[i][i+1]=(i+1)*(n-2*m+(i+1));
}
F.a[t][1]=1;
A=qkpow(A,k);F=A*F;
printf("%lld\n",F.a[m][1]*fast(inv,k)%MOD);
}