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: