当前位置: 首页 > 工具软件 > POG > 使用案例 >

BestCoder Round #43 第二题 pog loves szh II

咸琪
2023-12-01

pog loves szh II

 
 Accepts: 219
 
 Submissions: 834
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
pog在与szh玩游戏,首先pog找到了一个包含
   
   
    
    n
   
   个数的序列,然后他在这
   
   
    
    n
   
   个数中挑出了一个数A,szh出于对pog的爱,在余下的
   
   
    
    n−1
   
   个数中也挑了一个数B,那么szh与pog的恩爱值为
   
   
    
    (A+B)
   
   对
   
   
    
    p
   
   取模后的余数,pog与szh当然想让恩爱值越高越好,并且他们想知道最高的恩爱值是多少。
输入描述
若干组数据(不超过
   
   
    
    5
   
   组
   
   
    
    n≥1000
   
   )。
每组数据第一行两个整数
   
   
    
    n(2≤n≤100000)
   
   ,
   
   
    
    p(1≤p≤231−1)
   
   。
接下来一行
   
   
    
    n
   
   个整数
   
   
    
    ai(0≤ai≤231−1)
   
   。
输出描述
对于每组的每个询问,输出一行,表示pog与szh的最大恩爱值。
输入样例
4 4
1 2 3 0
4 4
0 0 2 2
输出样例
3
2

 由于序列中的数可能超过P,所以将所有的数读入后进行取模操作。之后将取模后的所有数从小到大排序。题目要求我们求不同位置的两个数的和在取模意义下的最大值,而现在所有数都是小于P且排好序的。因此设我任意选了两个数是X和Y,显然0≤X+Y≤2P−2。若X+Y<P,则这次选数的答案就是X+Y,若X+Y\gepP,则答案是X+Y−P。 

那么我们可以这样做:将其中最大的两个数字相加取模,设为一个可能的答案记录在ANS中。这个答案是第二种情况的最大值。再对排序好的序列进行枚举,对每个枚举到的数,找出最大的数,使这个数与枚举到的数相加后的和最大且小于P,将之记为可能的答案并于之前找到的最大值ANS进行比较。这个答案是第一种情况中的可能的最大值。而普通的枚举是要超时的,但是我们发现如果从小到大枚举第一个数,那么另一个匹配的数显然是从大到小的,因此可以用一个NOW记录当前另一个匹配的数的位置,每次枚举时NOW递减至符合条件。可以做到O(n)的时间复杂度。
综上所述,时间复杂度为快速排序的O(nlogn),空间复杂度为O(n)。注意一些特殊情况如同一个位置不能多次选。


#include <iostream>
#include <cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
int a[100010];


int main()
{
    int n,p;
    while(cin>>n>>p)
    {
        for(int i = 1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i]%=p;
        }
        sort(a+1,a+n+1);
        int ans = (a[n]+a[n-1])%p;
        int last = n;
        for(int i = 1; i<=n;i++)
        {
            while(last && a[last]+a[i]>= p) last--;
            if(last) ans = max(ans,a[last]+ a[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}


 类似资料: