cf#276-B-Maximum Value-(数学+暴力)/(二分)
2732 ワード
http://codeforces.com/contest/484/problem/B
n個の数をあげて、
n個の数の中でai%(aj)の最大値を求めて、ai>=ajを要求します
最初はいい考えはなかった
ajを列挙して、毎回探しに行きます k*ajの存在に最も近い数(k>=2)
どのように探すならば2つの方法があります1つは直接配列aを並べ替えて、毎回2分で最もk*ajに近い数を探します
複雑度はnlgnlgnであるべきである
vis配列を前に処理すると
vis[a[i] ]=a[i]
vis[i]=vis[i-1]
ではvis配列には,vis[i]がiに最も近い数(自分が存在すれば当然自分である)を格納する.
そこでajを列挙する場合は、vis【2*aj-1】、vis【3*aj-1】…vis【k*aj-1】にアクセスするだけです
複雑度はnlogn
列挙ajの複雑さはスクリーンと少し似ている. n/1+n/2+n/3+......n/nはnlogn程度
【もう1つ、列挙するときは、明らかに最大の数から列挙すべきで、答えができるだけ大きくなるので、枝を切ることができます.2つの方法は、大きいものから小さいものまで70+msです】
【枝をもう1本減らすことができます 】
2点以外の方法:
二分のやり方
n個の数をあげて、
n個の数の中でai%(aj)の最大値を求めて、ai>=ajを要求します
最初はいい考えはなかった
ajを列挙して、毎回探しに行きます k*ajの存在に最も近い数(k>=2)
どのように探すならば2つの方法があります1つは直接配列aを並べ替えて、毎回2分で最もk*ajに近い数を探します
複雑度はnlgnlgnであるべきである
vis配列を前に処理すると
vis[a[i] ]=a[i]
vis[i]=vis[i-1]
ではvis配列には,vis[i]がiに最も近い数(自分が存在すれば当然自分である)を格納する.
そこでajを列挙する場合は、vis【2*aj-1】、vis【3*aj-1】…vis【k*aj-1】にアクセスするだけです
複雑度はnlogn
列挙ajの複雑さはスクリーンと少し似ている. n/1+n/2+n/3+......n/nはnlogn程度
【もう1つ、列挙するときは、明らかに最大の数から列挙すべきで、答えができるだけ大きくなるので、枝を切ることができます.2つの方法は、大きいものから小さいものまで70+msです】
【枝をもう1本減らすことができます 】
2点以外の方法:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
__int64 min(__int64 a,__int64 b)
{return a<b?a:b;}
__int64 max(__int64 a,__int64 b)
{return a>b?a:b;}
__int64 tm[3000123];
__int64 vis[3000123];
int main()
{
__int64 i,j;
__int64 n;
scanf("%I64d",&n);
__int64 top=0;
for (i=1;i<=n;i++)
{
scanf("%I64d",&tm[i]);
if (tm[i]>top) top=tm[i];
vis[tm[i]]=tm[i];
}
for (i=1;i<=top*2;i++)
if (vis[i]==i)continue;
else
vis[i]=vis[i-1];
int maxx=0;
for (i=top;i>=1;i--)
{
if (vis[i]==i)
{
if (maxx>i-1) continue;
for (j=2*i-1;j<=top*2;j+=i)
{
maxx=max(maxx,vis[j]%i);
}
}
}
printf("%d
",maxx);
return 0;
}
二分のやり方
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
__int64 min(__int64 a,__int64 b)
{return a<b?a:b;}
__int64 max(__int64 a,__int64 b)
{return a>b?a:b;}
__int64 tm[3000123];
__int64 vis[3000123];
int main()
{
__int64 i,j;
__int64 n;
scanf("%I64d",&n);
__int64 top=0;
for (i=1;i<=n;i++)
{
scanf("%I64d",&tm[i]);
if (tm[i]>top) top=tm[i];
vis[tm[i]]=tm[i];
}
sort(tm+1,tm+1+n);
n=unique(tm+1,tm+1+n)-tm-1;
int maxx=0;
for (i=n;i>=1;i--)
{
int x=tm[i];
int k=2;
while(x*k-1<=top*2)
{
int it=upper_bound(tm+1,tm+1+n,x*k-1)-tm;
it--;
if (tm[it]%x>maxx ) maxx=tm[it]%x;
if (maxx>=x-1) break;
k++;
}
}
printf("%d
",maxx);
return 0;
}