E. Wish I Knew How to Sort

00gg개 있다고 하자.

dp[k]dp[k] 를 처음 gg개의 위치에 kk 개의 00이 있기위한 기댓값이라고 하자.

dp[g]=0dp[g]=0 이다. 모든 00이 앞에 gg 개에 모두 있다면 sorted 상태이기 대문이다.

점화식을 다음과 같이 세울 수 있다.

dp[k]dp[k]가 있을 때, 앞에 gg 개에서 11 인것을 고르고 나머지 (ng)(n-g) 에서 00 인것을 골라야 상태가 전이된다.

이 때의 확률은 pk=(gk)(gk)(n2)=2(gk)2n(n1)p_k=\dfrac{(g-k) \cdot (g-k)}{\binom{n}{2}}=\dfrac{2(g-k)^2}{n \cdot (n-1)} 이다.

앞에 gg 개에서 11 은 현재 gkg-k 개가 있고, 결국 뒤에서도 앞으로 와야할 00(gk)(g-k) 개가 있을 것이기 때문이다.

따라서 dp[k]=pkdp[k+1]+(1pk)dp[k]+1dp[k]=p_{k} \cdot dp[k+1]+(1-p_k) \cdot dp[k]+1 이다.

  • pkp_k의 확률로 앞 gg개에 00k+1k+1개 있는 상태로 넘어갈 수 있으므로 그 때의 기댓값과 pkp_k 를 곱한 값을 더한다.
  • (1pk)(1-p_k) 의 확률로 시행이 무의미하게 써지기 때문에 (1pk)dp[k](1-p_k) \cdot dp[k] 를 더한다.
  • 우린 이번으로 한 번의 시행을 했기 때문에 11 을 더한다.

이걸 풀면

dp[k]pk=pkdp[k+1]+1dp[k] \cdot p_k=p_k \cdot dp[k+1]+1

dp[k]=dp[k+1]+1pk=dp[k+1]+n(n1)2(gk)2dp[k]=dp[k+1]+\dfrac{1}{p_k}=dp[k+1]+\dfrac{n(n-1)}{2(g-k)^2} 이다.

처음에 gg 개의 위치에 00 이 있는 개수를 xx 라고 하면 dp[g]=0dp[g]=0 이고 정답은 dp[x]dp[x] 이다.

const ll mod = 998244353;  
inline ll md(ll x) { return md(mod, x); }  
inline ll poww(ll a, ll b) {  
   ll ret = 1;  
   while (b) {  
      if (b & 1) {  
         ret *= a;  
         if (~mod) ret %= mod;  
      }  
      a *= a;  
      if (~mod) a %= mod;  
      b >>= 1;  
   }  
   return ret;  
}  
inline int inv(int x) {  
   return poww(x, mod - 2);  
}  
void solve() {  
   int n;  
   cin >> n;  
   vi a(n);  
   fv(a);  
   int g = cntt(a, 0), x = 0;  
   for (int i = 0; i < g; i++) if (a[i] == 0) x++;  
  
   if (x == g) {  
      cout << 0 << endl;  
      return;  
   }  
  
   int val = 0;  
   for (int k = g - 1; k >= x; k--) {  
      val = md(val + md(md(md(md(n * (n - 1)) * inv(2)) * inv(g - k)) * inv(g - k)));  
   }  
   cout << val << endl;  
}

Comments