F - Zero Remainder Sum(dp)

https://codeforces.com/problemset/problem/1433/F

You are given a matrix aa of size n \times mn×m consisting of integers.

You can choose no more than \left\lfloor\frac{m}{2}\right\rfloor⌊ 
2
m

 ⌋ elements in each row. Your task is to choose these elements in such a way that their sum is divisible by kk and this sum is the maximum.

In other words, you can choose no more than a half (rounded down) of elements in each row, you have to find the maximum sum of these elements divisible by kk.

Note that you can choose zero elements (and the sum of such set is 00).

#include<iostream>
#include<algorithm>
#include<string> 
#include<set> 
#include<map>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<unordered_map>
#include<iomanip>
#define ll long long
#define ull unsigned long long
#define gg ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define m_p make_pair
#define pi acos(-1)
using namespace std;

const int N = 1e6 + 5;
const int M = 5e5 + 5;
const double eps = 1e-4;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9+7;

int n, m, k, dp[80][80][80][80];//前i行, 第i行前j个,选了k个 , 模数为r的最大数 ///开long long 会MLE
int a[80][80];

void solve()
{
	memset(dp, -1, sizeof dp);//-1表示没有余数为r的情况
	dp[1][0][0][0] = 0;//一个不选为0
	cin>>n>>m>>k;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			cin>>a[i][j];
		}	
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			for(int w = 0; w <= min(j, m/2); w++)//已选多少个 
			{
				for(int u = 0; u < k; u++)//模数
				{
					dp[i][j][w][u] = max(dp[i][j-1][w][u], dp[i][j][w][u]);//不选a[i][j]
					if(w && dp[i][j-1][w-1][u] != -1)//判断是否在之前余数为u时可选a[i][j]
						dp[i][j][w][(u + a[i][j]) % k] = max(dp[i][j][w][(u + a[i][j]) % k], dp[i][j - 1][w-1][u] + a[i][j]); 
				}	
				for(int ii = 0; ii < k; ii++)
					dp[i+1][0][0][ii] = max(dp[i][j][w][ii], dp[i+1][0][0][ii]);///将i行信息转移给下一行一个未选的情况
			}	
		}	
	}
	cout<<dp[n+1][0][0][0];
}

signed main()
{
	gg;
	ll t = 1;
//	cin>>t;
	while(t--)
		solve();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值