zoukankan      html  css  js  c++  java
  • [省选联考 2021 B 卷] 取模

    给出个数组(a),选择不同的三个下标(i,j,k),最大化((a_i+a_j)mod a_k)

    (nle 2*10^5)


    (a_i)排序。

    先讲暴力:枚举模数(a_k),令(b_i=a_i mod a_k)。分成两类:(b_i+b_jge a_k)(b_i+b_j<a_k)。其中,前者只需要算((a_{k-1}+a_{k-2})mod a_k)。证明:假如存在(p>k),且(a_{p} mod a_k>a_{k-2}),则有(a_{k-2}+a_k<a_p),此时选择((a_{k-2}+a_k)mod a_p)更优。后者可以求出(b_i)之后,排序,双指针计算。于是就做到了(O(n^2lg n))的复杂度。

    考虑优化这个暴力:先算(ans=max ((a_{k-2}+a_{k-1})mod a_k))。然后(k)从后往前枚举,如果(a_k-1>ans)则以(a_k)为模数计算上面后面的第二类。

    显然要考虑的(k)是一段后缀。下面证明只有(O(log V))个:

    假如最终的(ans)满足(ans<a_sle a_{s+1}le dots le a_n)

    根据第一类,有:(forall iin[s,n-2],ansge (a_i+a_{i+1})mod a_{i+2}ge a_i+a_{i+1}-a_{i+2})。于是有(a_{i+2}-ansge (a_{i}-ans)+(a_{i+1}-ans))。令(c_i=a_i-ans)(c_i>0),且(c_i)至少是类似斐波拉契数列增长的,而且(c_n=a_n-ans=O(V)),于是长度为(O(log V))级别。

    总时间(O(nlog nlog V))


    using namespace std;
    #include <bits/stdc++.h>
    #define N 200005
    int n;
    int a[N],b[N];
    int main(){
    //	freopen("in.txt","r",stdin);
    //	freopen("out.txt","w",stdout);
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i)
    		scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	int ans=0;
    	for (int i=3;i<=n;++i)
    		ans=max(ans,(a[i-2]+a[i-1])%a[i]);
    	for (int j=n;j>=1;--j)
    		if (a[j]-1>ans){
    			int k=0;
    			for (int i=1;i<j;++i) b[++k]=a[i];
    			for (int i=j+1;i<=n;++i) b[++k]=a[i]%a[j];
    			sort(b+1,b+k+1);
    //			ans=max(ans,(b[k]+b[k-1])%a[j]);
    			for (int i=k,p=1;i>=1;--i){
    				p=min(p,i-1);
    				while (p<=i-1 && b[p]+b[i]<a[j])
    					++p;
    				if (p>1)
    					ans=max(ans,(b[p-1]+b[i])%a[j]);
    			}
    		}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    继承与多态,Instanceof关键字
    面向对象,单例模式
    方法
    数组
    流程控制
    基础语法
    连接linux四大远程工具
    MYSQL-索引的设计
    银行一类(Ⅰ类)、二类(Ⅱ类)、三类(Ⅲ类)账户区别是什么?
    真正有效的学习
  • 原文地址:https://www.cnblogs.com/jz-597/p/14659879.html
Copyright © 2011-2022 走看看