51nod 1624 取余最长路

传送门

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注

佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和。

有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的娱乐值变为对p取模后的值,这让佳佳十分的不开心,因为她无法找到一条能使她得到最大娱乐值的路径了!

她发现这个问题实在是太困难了,既然这样,那就只在3*n的矩阵内进行游戏吧!

现在的问题是,在一个3*n的带权矩阵中,从(1,1)走到(3,n),只能往右往下移动,问在模p意义下的移动过程中的权总和最大是多少。


样例解释:

移动的方案为“下下右”。

Input
单组测试数据
第一行两个数n(1<=n<=100000),p(1<=p<=1000000000)。
接下来3行,每行n个数,第i行第j列表示a[i][j]表示该点的权(0<=a[i][j]<p)。
Output
一个整数表示答案。
Input示例
2 3
2 2
2 2
0 1
Output示例
2

 

题解转自:

http://www.cnblogs.com/wzj-is-a-juruo/p/5453140.html

不难发现路径可以拆成三条线段,只要知道两个转折点的位置就能计算出答案。

设sum(i,l,r)表示第i行从l到r元素的和,则答案可以表示为sum(1,1,x)+sum(2,x,y)+sum(3,y,n)%p。

前缀和一下转化成(S3[n]-S3[y-1])+S2[y]+(S1[x]-S2[x-1])%p,从小到大枚举y,将所有(S1[x]-S2[x-1])扔到一个集合里,用个set就能轻松实现了。

时间复杂度为O(NlogN)。

 

note:

1. (S3[n]-S3[y-1]) 可以反向处理,省时。

2. 

使用
it = s.lower_bound(p - re);
比
it = lower_bound(s.begin(),s.end(),p - re);
省时,后者会T

3. 注意减法的取模 要 加上 p,不然会出负数

4. 要考虑,

it = s.lower_bound(p - re); 如果 it 是 s.begin() ,那么表示,所有的数 都大于 p - re ,那么只能取最后一个数了。 
 
转:
 
 
C++
421 ms
11560 KB
Accepted
2016/05/18
10:15:10

 51

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <string>
 8 #include <vector>
 9 #include <queue>
10 #include <set>
11 
12 using namespace std;
13 
14 #define N 100005
15 #define mod 1000000007
16 #define ll long long
17 #define inf 0x3fffffff
18 
19 int n;
20 ll a[4][N];
21 ll sum[4][N];
22 ll p;
23 ll ans;
24 
25 int main()
26 {
27     int i,j;
28     //freopen("in.txt","r",stdin);
29     scanf("%d%I64d",&n,&p);
30     sum[1][0] = sum[2][0] = sum[3][0] = 0;
31     for(i = 1;i <= 3; i++){
32             //printf(" i = %d\n",i);
33         for(j = 1;j <= n;j++){
34             scanf("%d",&a[i][j]);
35             sum[i][j] = (sum[i][ j - 1] + a[i][j]) % p;
36         }
37     }
38     int y;
39     ans = 0;
40     set<ll> s;
41     set<ll>::iterator it;
42     ll re;
43     for(y = 1;y <= n;y++){
44         //printf(" y = %d\n",y);
45         s.insert( (sum[1][y] - sum[2][y - 1] + p) % p );
46         re = (sum[2][y] + sum[3][n] - sum[3][ y - 1] + p) % p;
47         it = s.lower_bound(p - re);
48         if(it == s.begin()){
49             ans = max(ans, (re + ( *(--s.end() ) ) )% p );
50         }
51         else{
52             ans = max(ans, (re + ( *(--it ) ) )% p );
53         }
54     }
55     printf("%I64d\n",ans);
56 
57     return 0;
58 }

 

posted on 2016-05-18 10:27  njczy2010  阅读(339)  评论(0编辑  收藏  举报