51nod 1624 取余最长路
Posted rosebud
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1624 取余最长路相关的知识,希望对你有一定的参考价值。
走的过程必然是这样的:从pos[1][1]走到pos[1][x]以至于pos[2][x],再走到pos[2][y]以至于pos[3][y],最后从pos[3][y]走到pos[3][n]。
假设第i层的前j项和为sum[i][j],其中i∈[1,3],j∈[1][n]。留意,这里x<=y。
那么这样一条转折点为x和y的路径所得的值为:
ans=sum[1][x]+(sum[2][y]-sum[2][x-1])+(sum[3][n]-sum[3][y-1])
对这个式子调整一下:
令①=sum[1][x]-sum[2][x-1];②=sum[2][y]-sum[3][y-1]+sum[3][n]
ans=①+②
相当于把x和y进行了分离,于是我们可以把①用set进行存储用以查询,穷举②。
穷举②的每一项的时候,set里有许多的①,那么哪一项才是好的呢?因为要mod P,因为所有元素都属于[0,P-1],所以:
要么让①+②最接近P,要么让①+②最接近2P,这样一模剩下来的才大。故而:
情况1:找<(p-②),且最接近这个值的,这样加起来会和会最接近P
情况2:情况1不存在,比如说set里的数都>=(p-②),那么直接找set里最大的那个就行。因为这样①+②能越过P之后尽可能往前走,使得数更大。
这里注意2个地方:
1:相减的地方可能产生负数,+P来调一下
2:这里的X是<=Y的,所以不能先把所有的①放进set再枚举②。得放一个①,②从前面的①构成的set里找。
#include <bits/stdc++.h> using namespace std; #define ll long long #define lowb lower_bound const int maxN = 1e5 + 5; ll N, P, sum[4][maxN]; set<ll> st; int main() { scanf("%lld%lld", &N, &P); ll t; for (int i = 1; i <= 3; ++i) { sum[i][0] = 0; for (int j = 1; j <= N; ++j) { scanf("%lld", &t); sum[i][j] = (sum[i][j - 1] + t) % P; } } st.clear(); ll ans = 0; for (int y = 1; y <= N; ++y) { st.insert((sum[1][y] - sum[2][y - 1] + P) % P); ll cur = (sum[2][y] - sum[3][y - 1] + sum[3][N] + P) % P; t = P - cur; set<ll>::iterator it = st.lowb(t); if (it != st.begin()) ans = max(ans, (*(--it) + cur) % P); else ans = max(ans, (*(--st.end()) + cur) % P); } printf("%lld ", ans); return 0; }
以上是关于51nod 1624 取余最长路的主要内容,如果未能解决你的问题,请参考以下文章