解いた問題のソースコードと解説など。


SRM 338 Div1 Medium RandomSwaps

問題

長さarrayLengthの配列がある。ここから無作為に2つの要素を取り出し、交換する動作をswapCount回行う。この後に当初a番目にあった要素がb番目に移動している確率を求めよ。

やりかた

典型的なDP。
dp[0][i]:=(i回スワップした後にbに移動している確率)
dp[1][i]:=(i回スワップした後にb以外に移動している確率)
でDP。


イカソース。

class RandomSwaps {
public:
  double getProbability(int arrayLength, int swapCount, int a, int b){
    memset(dp, 0, sizeof(dp));
    int N = arrayLength;
    if(a == b) dp[0][0] = 1;
    else dp[1][0] = 1;
    for(int i = 0; i < swapCount; i++){
      dp[0][i + 1] = dp[0][i] * (N - 2) / N + dp[1][i] * 2 / N / (N - 1);
      dp[1][i + 1] = dp[0][i] * 2.0 / N     + dp[1][i] * (1.0 - 2.0 / N / (N - 1));
    }
    return dp[0][swapCount];
  }
};

dp[0][i] + dp[1][i] = 1.0なので、どちらかは省略はできます。

Get up! 明日のSUPER ST@R!