牛客2020跨年场 B.牛牛想起飞

牛客2020跨年场 B.牛牛想起飞

题目链接

题目描述

给定一个长度为 n n n 的序列 a a a 和一个长度为 n n n 的序列 b b b,对于序列中的每一个数字 a i a_i ai,牛牛都可以进行以下操作:
(1) 将数字 a i a_i ai a i a_i ai 变成 a i + b i a_i + b_i ai+bi
(2) 将数字 a i a_i ai a i a_i ai 变成 a i − b i a_i - b_i aibi
牛牛很懒,所以每个数字只能最多进行一次操作,甚至不操作。现在给出一个数字 y ,牛牛想要知道在做合理的操作后能得到模 y 意义下的最大序列和是多少。
换句话说,设 a 1 ′ , a 2 ′ , a 3 ′ … a n ′ a_1' ,a_2', a_3'\dots a_n' a1,a2,a3an 是最终得到的 数组的样子,你要使得 ( a 1 ′ + a 2 ′ + a 3 ′ ⋯ + a n ′ )   m o d   y (a_1' + a_2' + a_3'\dots +a_n') \ mod \ y (a1+a2+a3+an) mod y 结果最大化。
做出这道题他就能起飞,你能帮帮他吗?

输入描述:

第一行输入 n , y ( 1 ≤ n ≤ 1 0 5 , 1 ≤ y ≤ 100 ) n, y(1 \leq n \leq 10^5, 1 \leq y \leq 100) n,y(1n105,1y100)
第二行输入 n n n 个整数 a i ( 0 ≤ a i ≤ 1 0 5 ) a_i(0 \leq a_i \leq 10^5) ai(0ai105)
第三行输入 n n n 个整数 b i ( 0 ≤ b i ≤ 100 ) b_i (0 \leq b_i \leq 100) bi(0bi100)

输出描述:

输出能得到模 y 意义下的最大序列和

示例1

输入

3 100
1 2 3
1 1 1

输出

9

动态规划~
d p [ i ] [ j ] dp[i][j] dp[i][j] i i i 个数通过操作后取模可以得到值 j j j,则有状态转移方程:

i f   d p [ i − 1 ] [ j ]   t h e n   { d p [ i ] [ ( j + a [ i ] ) % y ] = 1 d p [ i ] [ ( j + a [ i ] + b [ i ] ) % y ] = 1 d p [ i ] [ ( j + a [ i ] − b [ i ] ) % y ] = 1 if\ dp[i-1][j]\ then\ \begin{cases} dp[i][(j+a[i])\%y]=1\\ dp[i][(j+a[i]+b[i])\%y]=1\\ dp[i][(j+a[i]-b[i])\%y]=1 \end{cases} if dp[i1][j] then dp[i][(j+a[i])%y]=1dp[i][(j+a[i]+b[i])%y]=1dp[i][(j+a[i]b[i])%y]=1
AC代码如下:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
bool dp[N][105];
int n, a[N], b[N], y;

int mod(int x) {
    return x < 0 ? (y - (-x) % y) % y : x % y;
}

int main() {
    cin >> n >> y;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];
    dp[1][mod(a[1])] = 1;
    dp[1][mod(a[1] + b[1])] = 1;
    dp[1][mod(a[1] - b[1])] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= y; j++) {
            if (dp[i - 1][j]) {
                dp[i][mod(j + a[i])] = 1;
                dp[i][mod(j + a[i] + b[i])] = 1;
                dp[i][mod(j + a[i] - b[i])] = 1;
            }
        }
    }
    for (int i = y - 1; i >= 0; i--) {
        if (dp[n][i]) {
            cout << i;
            return 0;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺 崽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值