pog loves szh II_(HDU-5265)

(两个数的和用二分接近mod)

题意:

给出n,p,n个数,从中取两个数 a,b , 求出( a + b )% p 的最大值。

解析:

先把每个数%p , 可以发现两个数加起来,要么 < p,要么 ≥ p,然后小于 2p。 
那么对于大于p的,必定是最大那两个数加起来%p,满足贪心的。 

小于p的话,就可以直接找,二分可以,因为满足单调性。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
ll n,p,a[N];
inline void read(ll &x) {
    int flag = 0;
    x = 0;
    char c = getchar();
    if(c == '-')
        flag = 1;
    while(c < '0' || c > '9') {
        if(c == '-')
            flag = 1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
        x = x * 10 + c - '0', c = getchar();
    if(flag) x = -x;
}
int main() {
    while(~scanf("%lld%lld", &n, &p)) {
        ll maxz = 0;
        for(int i = 0; i < n; i++) {
            read(a[i]);
            a[i] %= p;
            maxz = max(maxz, a[i]);
        }
        sort(a, a+n);

        ll ans = (a[n-1] + a[n-2]) % p;
        for(int i = 0; i < n-1; i++) {
            ll val = p - a[i] - 1;
            int pos = upper_bound(a, a+i-1, val)-a-1;
/* 对于upper_bound来说,返回的是被查序列中第一个大于查找值的指针,也就是返回指向被查值>查找值的最小指针,
lower_bound则是返回的是被查序列中第一个大于等于查找值的指针,也就是返回指向被查值>=查找值的最小指针。 */
            if(pos == -1) {
                ans = max(ans, (a[i] + maxz) % p);
            }else {
                ans = max(ans, (a[pos] + a[i]) % p);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值