51nod 1624取余最长路

来源:互联网 发布:淘宝搜血滴子 编辑:程序博客网 时间:2024/05/06 17:06

题意:3*n(n<1e5)的方格,每个方格内有一个数字,从(1,1)走到(3,n)(只能向下或向右),走过格子的和,膜p后的最大值是多少

题解:如果是普通的不需要膜的话,就是普通的dp,但是有膜以后,会产生后效性,因此,就不会dp了

           如果暴力的话,复杂度n^2

           换个角度,也就是找两个拐点,使得sum[1][x]+sum[2][y]-sum[2][x-1]+sum[3][n]-sum[3][y-1]最大就可以

           考虑优化,对于sum[2][y]-sum[3][y-1]+sum[3][n],只要找到前面的“最大”的sum[1][x]-sum[2][x-1]就可以

           可以把前面所有的sum[1][i]-sum[2][i-1]保存起来,然后二分找就可以

int a[10][100010];LL sum[10][100010];int main(){    mem(a,0);    mem(sum,0);    int n;    LL p;    cin>>n>>p;    for(int i=1;i<=3;i++){        for(int j=1;j<=n;j++){            scanf("%d",&a[i][j]);            sum[i][j]=(sum[i][j-1]+a[i][j])%p;        }    }    set <int> s;    s.clear();    LL ans=(sum[1][n]+a[2][n]+a[3][n])%p;    for(int i=1;i<=n;i++){        LL temp=(sum[1][i]-sum[2][i-1]+p)%p;        s.insert(temp);        temp=(sum[2][i]-sum[3][i-1]+sum[3][n]+p)%p;        ///不超过p,且能达到的最大值        set <int>::iterator it = s.lower_bound(p-temp);        if(it!=s.begin())            ans=max(ans,(temp+*(--it))%p);    }    cout<<ans<<endl;    return 0;}


0 0
原创粉丝点击