Official
D - I Hate Non-integer Number Editorial by m_99
選んだ項が \(x_1,\ldots,x_i\) の時、平均値は \(\frac {x_1+\ldots+x_i}{i}\) となります。この値が整数であるための必要十分条件は、この式の分子の部分、すなわち選んだ項の総和が \(i\) の倍数であることです。
ここで、\(i=1,\ldots,N\) に対して次のような \(\mathrm {dp}\) を考えます。
- \(\mathrm{dp}_{j,k,l}\) : \(A\) の先頭 \(j\) 項から \(k\) 個の項を選ぶ方法であって、選んだ項の総和を \(i\) で割った余りが \(l\) となるようなものの個数を \(998244353\) で割った余り
すると、答えは \(\mathrm{dp}_{N,i,0}\) の総和となります。
\(\mathrm{dp}\) の遷移については実装例を参考にしてください。( \(23\) 行目が \(a_j\) を選ばない場合に、\(24\) 行目が \(a_j\) を選ぶ場合に対応しています)
実装例(C++)
#include <bits/stdc++.h>
#include <atcoder/modint>
using namespace std;
using namespace atcoder;
using mint = modint998244353;
int main() {
int N;
cin>>N;
vector<int> a(N);
for(int i=0;i<N;i++)cin>>a[i];
mint ans = 0;
for(int i=1;i<=N;i++){
vector dp(N+1,vector(i+1,vector<mint>(i,0)));
dp[0][0][0] = 1;
for(int j=0;j<N;j++){
for(int k=0;k<=i;k++){
for(int l=0;l<i;l++){
dp[j+1][k][l] += dp[j][k][l];
if(k!=i)dp[j+1][k+1][(l+a[j])%i] += dp[j][k][l];
}
}
}
ans += dp[N][i][0];
}
cout<<ans.val()<<endl;
return 0;
}
posted:
last update: