• 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
    ",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 }
  • 相关阅读:
    Eclipse部署项目到Tomcat中,class文件夹为空的解决方案
    微软(北京).NET俱乐部活动 (2010年6月26日) – Visual Studio 2010 /*LIFE RUNS ON CODE*/
    失望的Vista SP1
    急聘BI DW OLAP开发工程师 (北京)
    急聘.NET开发工程师 (北京)
    开篇
    Windows Vista User Account Control (UAC) 全新安全模块“用户帐户控制”
    Tidy your desktop
    [导入]Vista的屏幕截图小工具:Snipping Tool
    微软发布官方TFS 2010 Scrum 模板
  • 原文地址:https://www.cnblogs.com/njczy2010/p/5504275.html
Copyright © 2020-2023  润新知