HDU 5265 pog loves szh II(二分)

题意:

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

解析:

先把每个数%p , 可以发现两个数加起来,要么 < p,要么 ≥ p,然后小于 2p。
那么对于大于p的,必定是最大那两个数加起来%p,满足贪心的。
小于p的话,就可以直接找,二分可以,因为满足单调性。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int N = 100005;

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 n;
ll p;
ll a[N];
int main() {
    //freopen("in.txt", "r", stdin);
    while(scanf("%d%lld", &n, &p) != EOF) {
        ll maxv = 0;
        for(int i = 0; i < n; i++) {
            read(a[i]);
            a[i] %= p;
            maxv = max(maxv, 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;
            if(pos == -1) {
                ans = max(ans, (a[i] + maxv) % 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、付费专栏及课程。

余额充值