【数学 随机 技巧】cf364D. Ghd

随机化选讲的例题

John Doe offered his sister Jane Doe find the gcd of some set of numbers a.

Gcd is a positive integer g, such that all number from the set are evenly divisible by g and there isn't such g(g' > g), that all numbers of the set are evenly divisible by g'.

Unfortunately Jane couldn't cope with the task and John offered her to find the ghd of the same subset of numbers.

Ghd is a positive integer g, such that at least half of numbers from the set are evenly divisible by g and there isn't such g(g' > g) that at least half of the numbers from the set are evenly divisible by g'.

Jane coped with the task for two hours. Please try it, too.

Input

The first line contains an integer n (1 ≤ n ≤ 106) showing how many numbers are in set a. The second line contains space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 1012). Please note, that given set can contain equal numbers.

Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the %I64d specifier.

Output

Print a single integer g — the Ghd of set a.


题目分析

随机化+复杂度分析

首先按照随机化题的处理方式,随机选一个数$a_{pos}$钦定它在答案集合内。再考虑如何找出剩下数中满足条件的最大公因数。由于这个公因数一定是$d=\gcd\{a_{pos},a_i\}$,并且所有$d|d'$的$d'$也都会算在$d$的贡献里。那么这里由复杂度分析的经验得,由于$10^{12}$内因数最多的数约有$7000$个约数,那么我们并不需要对$d$存下所有$d'$的贡献,而是每次暴力地累计答案即可。

话说为什么这个srand(time(0))的随机化正确率这么低……只有选15个数才能擦着时限过去。

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 const int maxn = 1000035;
 4 
 5 int n;
 6 ll a[maxn],ans;
 7 std::map<ll, int> mp;
 8 std::map<ll, int>::iterator it,tmp;
 9 
10 ll read()
11 {
12     char ch = getchar();
13     ll num = 0;
14     for (; !isdigit(ch); ch=getchar());
15     for (; isdigit(ch); ch=getchar())
16         num = (num<<1)+(num<<3)+ch-48;
17     return num;
18 }
19 ll gcd(ll a, ll b){return !b?a:gcd(b, a%b);}
20 int main()
21 {
22     srand(time(0)), n = read();
23     for (int i=1; i<=n; i++) a[i] = read();
24     for (int cse=15; cse; --cse)
25     {
26         mp.clear();
27         int pos = 1ll*rand()*rand()%n+1;
28         if (a[pos] <= ans) continue;
29         for (int i=1; i<=n; i++)
30         {
31             ll val = gcd(a[pos], a[i]);
32             if (val > ans) ++mp[val];
33         }
34         it = mp.end();
35         for (int cnt; it!=mp.begin(); )
36         {
37             cnt = 0, --it;
38             if ((*it).first <= ans) break;
39             for (tmp=it; tmp!=mp.end(); ++tmp)
40                 if (!((*tmp).first%(*it).first)) cnt += (*tmp).second;
41             if (cnt >= (n+1)/2) ans = (*it).first;
42         }
43     }
44     printf("%lld\n",ans);
45     return 0;
46 }

 

 

 

 

END

posted @ 2019-03-31 15:29  AntiQuality  阅读(318)  评论(0编辑  收藏  举报