基准时间限制: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 ",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 ",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 ",ans); 56 57 return 0; 58 }