1. 程式人生 > >51nod 1421 最大MOD值 codeforce 484B. Maximum Value【調和級數複雜度T_T】

51nod 1421 最大MOD值 codeforce 484B. Maximum Value【調和級數複雜度T_T】

文章目錄

題目連結:

51nod 1421
cf484B

參考部落格:https://blog.csdn.net/linkfqy/article/details/78300976
對哈,裡面那層迴圈的複雜度是調和級數,數越大列舉這個數的倍數就越小

然後就是找一段範圍內最大的數,最開始竟然沒有反應過來,就是找這段範圍的最右邊看在哪裡,他的左邊一個不就是這段範圍裡最大的嘛~

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=
2e5+5; int a[maxn]; int main() { int N; while(cin>>N) { int ans=0; for(int i=1;i<=N;i++)scanf("%d",a+i); sort(a+1,a+1+N); for(int i=1;i<=N;i++) { if(a[i]==a[i-1])continue;//只要第一個來判斷 for(int k=2;k*a[i]<=a[N];k++) { int pos=lower_bound(a+1,a+1+N,k*a[i])-a; ans=
max(ans,a[pos-1]%a[i]);//找到a[pos]這個數,再往前面一個數a[pos-1]肯定在[k*ai,(k+1)*ai]範圍內 } ans=max(ans,a[N]%a[i]);//剩下不夠倍數的一段,最後的是最大的 } cout<<ans<<endl; } }

然後就是因為 a i a_i

的資料範圍是1e6,所以闊以用個數組b[i]來儲存小於 i 的最大的a[]陣列中的數是多少,這樣中間那層二分就變成 O ( 1 ) O(1) 的了。用這種方法只跑了109ms,而上面二分那個跑路608ms,優化很明顯呀~

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
int a[maxn],b[maxn*5];//b[i]表示a[]陣列中比i小的最大的數 
int main()
{
	int N;
	while(cin>>N)
	{
		int ans=0;
		for(int i=1;i<=N;i++)scanf("%d",a+i);
		sort(a+1,a+1+N);
		N=unique(a+1,a+1+N)-(a+1);
		for(int i=1,j=0;i<=1000000;)
		{
			if(i>a[j]&&i<=a[j+1])b[i++]=a[j];
			else if(j==N)b[i++]=a[N];
			else j++;
		}
		for(int i=1;i<=N;i++)
		{
			for(int k=2;k*a[i]<=a[N];k++)
			{
				ans=max(ans,b[k*a[i]]%a[i]);
			}
			ans=max(ans,a[N]%a[i]);//剩下不夠倍數的一段,最後的是最大的 
		}
		cout<<ans<<endl;
	}
}