Official

D - Max Multiple Editorial by m_99


次のような動的計画法を考えます。

  • dpi,j,k\mathrm{dp}_{i,j,k} : a1,,aia_1,\ldots,a_i から jj 個が選ばれていて、総和を DD で割った余りが kk であるようなときの総和の最大値(不可能なら 1-1 )

すると、答えは dpN,K,0\mathrm{dp}_{N,K,0} です。

遷移は、aia_i を選ぶ場合と選ばない場合を考えます。前者では jj11 増え、kkaia_i の値に応じて変わります。後者では j,kj,k がともに変わりません。

より詳細には実装例を参考にしてください。

実装例 (C++)

Copy
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. int N,K,D;
  5. cin>>N>>K>>D;
  6. vector<int> a(N);
  7. for(int i=0;i<N;i++)cin>>a[i];
  8. vector dp(N+1,vector(K+1,vector<long long>(D,-1)));
  9. dp[0][0][0] = 0;
  10. for(int i=0;i<N;i++){
  11. for(int j=0;j<K+1;j++){
  12. for(int k=0;k<D;k++){
  13. if(dp[i][j][k]==-1)continue;
  14. //a_i を選ばない場合の遷移
  15. dp[i+1][j][k] = max(dp[i+1][j][k],dp[i][j][k]);
  16. //a_i を選ぶ場合の遷移
  17. if(j!=K){
  18. dp[i+1][j+1][(k+a[i])%D] = max(dp[i+1][j+1][(k+a[i])%D],dp[i][j][k] + a[i]);
  19. }
  20. }
  21. }
  22. }
  23. cout<<dp[N][K][0]<<endl;
  24. return 0;
  25. }
#include <bits/stdc++.h>
using namespace std;

int main() {
    
	int N,K,D;
	cin>>N>>K>>D;
	
	vector<int> a(N);
	for(int i=0;i<N;i++)cin>>a[i];
	
	vector dp(N+1,vector(K+1,vector<long long>(D,-1)));
	dp[0][0][0] = 0;
	
	for(int i=0;i<N;i++){
		for(int j=0;j<K+1;j++){
			for(int k=0;k<D;k++){
				if(dp[i][j][k]==-1)continue;
				
				//a_i を選ばない場合の遷移
				dp[i+1][j][k] = max(dp[i+1][j][k],dp[i][j][k]);
				
				//a_i を選ぶ場合の遷移
				if(j!=K){
					dp[i+1][j+1][(k+a[i])%D] = max(dp[i+1][j+1][(k+a[i])%D],dp[i][j][k] + a[i]);
				}
			}
		}
	}
	
	cout<<dp[N][K][0]<<endl;
	
	return 0;
}

posted:
last update:



2025-04-15 (Tue)
18:04:19 +00:00