hdu-5265pog loves szh II

pog loves szh II

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1357    Accepted Submission(s): 391


Problem Description
Pog and Szh are playing games.There is a sequence with  n  numbers, Pog will choose a number A from the sequence. Szh will choose an another number named B from the rest in the sequence. Then the score will be  (A+B)  mod  p .They hope to get the largest score.And what is the largest score?
 

Input
Several groups of data (no more than  5  groups, n1000 ).

For each case: 

The following line contains two integers, n(2n100000) p(1p2311)

The following line contains  n  integers  ai(0ai2311)
 

Output
For each case,output an integer means the largest score.
 

Sample Input
  
  
4 4 1 2 3 0 4 4 0 0 2 2
 

Sample Output
  
  
3 2
 


题意:给你N个数和一个数P,让你找出两个数A和B,使得(A+B)%P的值最大,并且输出这个最大值
思路:拿到题,首先就是将读入的数先取模模P,然后排序。然后我就得到了N个0到P-1的数,从这些数中找出两个不同的数,他们的和范围是0到2P-2。
那么分两种情况考虑:考虑和大于等于P的情况,显然若两个数相加大于P并且模完P还是最大,那么肯定取最大的两个数(若两个数相加小于P,那么只是退化到和小于P的情况,造成多判的情况,并不会影响最后答案的正确)
然后考虑和小于P的情况:这里有两种做法。
1是遍历所有数(其实并不需要所有,这里还可以优化),将P-你正在遍历的数,然后在数组二分查找小于这个数的最大数,(这里要保证不能同时取同一个数两次)更新两个数加起来的最大值,即为答案。
2是设双指针,一头一尾,如果当前和大于等于P,尾指针-1;如果当前和小于P,头指针+1;循环条件是头指针小于尾指针。在过程中不断更新最大值。
综合考虑两种做法:二分实现起来麻烦,而且需要验证是否为同一个数,且复杂度为O(nlogn)
                                双指针比较好写,且复杂度为O(n);
虽然总的复杂度还是排序的nlogn,但还是推荐第二种写法
#include <cstdio>
#include <algorithm>
#define maxn 100000+5
using namespace std;
typedef long long ll;
ll a[maxn];
void read(ll& x)
{
    x=0;
    int flag=0;
    char c=getchar();
    if(c=='-')flag=1;
    while(c<'0'||c>'9')
    {
        if(c=='0')flag=1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    if(flag)x=-x;
}
int main()
{
    ll n,p;
    while(~scanf("%lld %lld",&n,&p))
    {
        for(int i=0;i<n;i++)
        {
            read(a[i]);
            a[i]%=p;
        }
        sort(a,a+n);
        ll ans=(a[n-1]+a[n-2])%p;
        int l=0,r=n-1;
        while(l<r)
        {
            ans=max(ans,(a[l]+a[r])%p);
            if(a[l]+a[r]<p)l++;
            else r--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值