AtCoder Regular Contest 060 C - 高橋君とカード
問題
問題概要
N枚のカードがあり、i番目(1-index)のカードには整数x[i-1]が書かれている。
何枚かカードを選びカードの整数の平均がAとなるようにしたい。そのような選び方は何通りあるか。
解法
平均を平均のまま扱うのは大変なので合計と個数を扱う。
dp[i][j][k] : i番目(1-index)まで見てj枚選び、合計がkである通り数。
0≦i≦N、0≦j≦N、0≦k≦Σx[i-1]
こうすれば答えは
i=Nかつk=j*Aとなるdp[i][j][k]の合計である。(j=0かつk=0の時を除く)
i番目のカードを選ぶか選ばないかの2通りある。
i番目のカードを選ばないとき
dp[i][j][k]=dp[i-1][j][k]
i番目のカードを選ぶとき
dp[i][j][k]=dp[i-1][j-1][k-x[i-1]]
これらの合計となる。
しかしj-1<0またはk-x[i-1]<0の時は配列外参照となるため
dp[i][j][k]=dp[i-1][j][k]
となる。
i=0の時
j=0かつk=0の時はdp[i][j][k]=1
それ以外の時はdp[i][j][k]=0
ソースコード
signed main() { int N, A; cin >> N >> A; vector<int>x(N); int Sx = 0; rep(i, N) { cin >> x[i]; Sx += x[i]; } vector<vector<vector<int>>>dp(N + 1, vector<vector<int>>(N + 1, vector<int>(Sx + 1))); rep(i, N + 1) { rep(j, N + 1) { rep(k, Sx + 1) { if (i == 0) { if (j == 0 && k == 0) { dp[i][j][k] = 1; } else { dp[i][j][k] = 0; } } else { if (j - 1 < 0 || k - x[i - 1] < 0) { dp[i][j][k] = dp[i - 1][j][k]; } else { dp[i][j][k] = dp[i - 1][j][k] + dp[i - 1][j - 1][k - x[i - 1]]; } } } } } int ans = 0; rep(i, N + 1) { rep(j, N + 1) { rep(k, Sx + 1) { if (i == N && k == j * A && j!=0 && k!=0) { ans += dp[i][j][k]; } } } } cout << ans << endl; }