51Nod - 1421 最大MOD值

190 篇文章 2 订阅
48 篇文章 0 订阅

题面

题意

给出n个数,求其中选择两个数,较大的数模较小的数的最大值。

做法

一开始想到的算法很奇怪,对于a求它模那个数的值最大,将小于a的数小于等于它的最大倍数放到set中,然后在增大a的同时,不断更新set中的数字的值,然后不断取最大值即可。
时间复杂度好像最劣是O(n*log(n)^2).

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#define P pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define N 200100
using namespace std;

int n,num[N],t,ans;
P tmp;
set<P>se;

int main()
{
    int i,j;
    cin>>n;
    for(i=1; i<=n; i++)
    {
        scanf("%d",&num[i]);
    }
    sort(num+1,num+n+1);
    se.insert(mp(num[2]/num[1]*num[1],num[1]));
    for(i=2; i<=n; i++)
    {
        for(;;)
        {
            tmp=(*se.begin());
            if(num[i]/tmp.se != tmp.fi/tmp.se)
            {
                se.erase(tmp);
                se.insert(mp(num[i]/tmp.se*tmp.se,tmp.se));
            }
            else
            {
                ans=max(ans,num[i]%tmp.se);
                break;
            }
        }
        se.insert(mp(num[i+1]/num[i]*num[i],num[i]));
    }
    cout<<ans;
}

虽然A了,但时间复杂度终究不对。

标算

首先预处理出,在原来数列中小于i的最大数。
然后算小于a[i]的k倍的最大数,即可更新答案。
也就是对于数字i,计算i~2* i,2* i~3* i,3* i~4* i……中的被除数。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 200100
#define M 2001000//注意要多开一倍,因为num[i]*j可能大于1000000
using namespace std;

int n,m,num[N],pos[M],t,ans;
bool P[M];

int main()
{
    int i,j,p,q;
    cin>>n;
    for(i=1; i<=n; i++)
    {
        scanf("%d",&p);
        if(P[p]) continue;
        P[p]=1;
        num[++m]=p;
    }
    n=m;
    sort(num+1,num+n+1);
    for(i=M-1000,j=n;i>=1;i--)
    {
        if(num[j]==i&&j>1) j--;
        pos[i]=num[j];
    }
    for(i=1;i<=n;i++)
    {
        for(j=2;num[i]*j<=M-1000;j++)
        {
            ans=max(ans,pos[num[i]*j]%num[i]);
        }
    }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值