牛客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
ai−bi。
牛牛很懒,所以每个数字只能最多进行一次操作,甚至不操作。现在给出一个数字 y ,牛牛想要知道在做合理的操作后能得到模 y 意义下的最大序列和是多少。
换句话说,设
a
1
′
,
a
2
′
,
a
3
′
…
a
n
′
a_1' ,a_2', a_3'\dots a_n'
a1′,a2′,a3′…an′ 是最终得到的 数组的样子,你要使得
(
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(1≤n≤105,1≤y≤100)
第二行输入
n
n
n 个整数
a
i
(
0
≤
a
i
≤
1
0
5
)
a_i(0 \leq a_i \leq 10^5)
ai(0≤ai≤105)
第三行输入
n
n
n 个整数
b
i
(
0
≤
b
i
≤
100
)
b_i (0 \leq b_i \leq 100)
bi(0≤bi≤100)
输出描述:
输出能得到模 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[i−1][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;
}