給你個數,求一個儘量大的數,使得數列中有超過個數能被該數整除。
數
發現每一個數出現在能被整除的集合中的概率均,於是考慮隨機。每一次猜測一個數在這個集合中,然後計算與其它數的gcd。最後查找一個最大的出現次數超過的gcd即可。(若則)
我們分析一下這樣做的正確率。每一次選對的概率,所以說一次選錯的概率,即隨機次的成功率爲。當取約時,其成功率可以接受。
#include<bits/stdc++.h>
#define reg register
#define ll long long
using namespace std;
const int mn = 1000005;
ll a[mn], res[mn];
int sum[mn];
inline ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
int main()
{
srand(time(NULL));
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%I64d", &a[i]);
ll ans = 1;
for(int T = 0; T < 13; T++)
{
int pos = ((rand() << 15) + rand()) % n + 1;
if(a[pos] <= ans) continue;
ll maxs = 1;
for(reg int i = 1; i <= n; i++)
res[i] = gcd(a[i], a[pos]), maxs = max(res[i], maxs);
if(maxs <= ans) continue;
sort(res + 1, res + 1 + n); int cnt = 0;
for(reg int i = 1; i <= n; i++)
{
if(res[i] != res[i - 1])
res[++cnt] = res[i], sum[cnt] = 0;
++sum[cnt];
}
for(reg int i = cnt; i; i--)
{
if(ans >= res[i]) break;
int tmp = 0;
for(int j = i; j <= cnt; j++)
if(res[j] % res[i] == 0) tmp += sum[j];
if((tmp << 1) >= n) {ans = res[i]; break;}
}
}
printf("%I64d\n", ans);
}