题目描述
Alice 有 nnn 个正整数,数字从 1∼n1 sim n1∼n 编号,分别为 a1,a2,…,ana_1,a_2, dots , a_na1,a2,…,an。
Bob 刚学习取模运算,于是便拿这 nnn 个数进行练习,他写下了所有
ai mod aj(1≤i,j≤n∧i≠j)a_i mod a_j (1 le i,j le n wedge i eq j) aimodaj(1≤i,j≤n∧i�=j)
的值,其中 mod modmod 表示取模运算。
Alice 想知道所有的结果中,严格次大值是多少。将取模后得到的所有值进行去重,即相同的结果数值只保留一个,剩余数中第二大的值就称为严格次大值。
输入格式
第一行一个正整数 nnn,表示数字个数。
第二行 nnn 个正整数表示 aia_iai。
输出格式
仅一行一个整数表示答案。
若若取模结果去重后剩余数字不足两个,则输出 −1-1−1。
输入输出样例
4 4 5 5 6
4
4 1 1 1 1
-1
7 12 3 8 5 7 20 15
12
说明/提示
【数据范围】
对于 40%40\%40% 的数据,1≤n,ai≤1001le n,a_i le 1001≤n,ai≤100;
对于 70%70\%70% 的数据,1≤n≤30001le n le 30001≤n≤3000,1≤ai≤1051le a_i le 10^51≤ai≤105;
对于 100%100\%100% 的数据,3≤n≤2×1053 le n le 2 imes 10^53≤n≤2×105,1≤ai≤1091le a_i le 10^91≤ai≤109。
【样例 111 解释】
所有取模的结果为 {4,4,4,1,0,5,1,0,5,2,1,1}{4,4,4,1,0,5,1,0,5,2,1,1}{4,4,4,1,0,5,1,0,5,2,1,1}。
去重后有:{0,1,2,4,5}{0,1,2,4,5 }{0,1,2,4,5},结果为 444。
根据题意要求,最后我们是要进行去重操作的,所以不管在哪里去重都是可以的,所以我们先对于读入数据进行去重,然后从小到大排序,因为我们知道,每个元素都需要和除他之外的所有元素进行比较,所以我们这样的操作其实对于我们最后的操作是没有影响的;
然后,转折点来了qwq
到这一步其实正解是一种非常简单的做法,但是由于本人过于蒟蒻,所以我的方法是两层循环,为了降低复杂度,我们发现,从小到大对元素进行排序之后,如果a%b中b的值大于a,那么就是说之后所有元素的值都大于a,所以a%他们其实结果就是a,依据这样的方法,我开心的把代码敲了出来,开心的交了上去,然后开心的发现自己最后三个点T了qwq
也就是说上面这种方法虽然在一定程度上降低了时间复杂度,但是对于某些特殊数据,它的复杂度还是太高的,所以我们来想另外的方法
其实在第一种方法中我们就可以发现,有由于所有元素都是从小到大排序的,所以除了最后一个元素之外,每一个元素取余的最大值就是他自己,所以严格次大值其实就是倒数第三个数的值,but,题目中还有一个坑点在于他没有规定i j的比较顺序,也就是说,可以用大数%小数,这样的话得到的数一定比大数小,按照常理来说,这种情况可以很容易被排除,但是不要忘了我们还有最后一个个元素呢!我们不知道最后一个元素%倒数第二个元素的值与倒数第三个元素的值到底谁大谁小,所以应该再取一次MAX才对
70分代码(本人第一遍写的qwq)
#include<bits/stdc++.h> using namespace std; int n; int vis[5020000]; int num=0; int ans[5020000]; int a[5020000]; int main() { cin>>n; for(int i=1; i<=n; i++) { int x; cin>>x; if(!vis[x]) { num++; vis[x]=1; a[num]=x; } } sort(a+1,a+num+1);// small int c=0; for(int i=1; i<=num; i++) { bool flag=0; for(int j=1; j<=num; j++) { if(a[i]==a[j]) continue; if(a[i]>a[j]&&flag==1) break; c++; ans[c]=a[i]%a[j]; } } num=0; int b[502000]; memset(vis,0,sizeof(vis)); sort(ans+1,ans+1+c); for(int i=1; i<=c; i++) { int x=ans[i]; if(!vis[ans[i]]) { num++; vis[ans[i]]=1; b[num]=ans[i]; } } sort(b+1,b+1+num); if(num==0) cout<<-1<<endl; else cout<<b[num-1]<<endl; return 0; }
正解(AC代码):
#include<bits/stdc++.h> using namespace std; int n; int vis[5020000]; int num=0; int ans[5020000]; int a[5020000]; int b[5020000]; int main() { cin>>n; for(int i=1; i<=n; i++) { int x; cin>>x; if(!vis[x]) { num++; vis[x]=1; a[num]=x; } } sort(a+1,a+num+1);// small if(num>=3) cout<<max(a[num-2],a[num]%a[num-1])<<endl; else cout<<-1<<endl; return 0; }
完结撒花✿✿ヽ(°▽°)ノ✿
根据题意要求,最后我们是要进行去重操作的,所以不管在哪里去重都是可以的,所以我们先对于读入数据进行去重,然后从小到大排序,因为我们知道,每个元素都需要和除他之外的所有元素进行比较,所以我们这样的操作其实对于