zoukankan      html  css  js  c++  java
  • Bzoj3837 [Pa2013]Filary(随机化)

    题面

    权限题

    题解

    这题有一个很好的性质,就是一定有$k>frac n2$。接着考虑怎么做。

    我们随机选取一个数$x$,然后将所有数与它作差,那么只需要找出$k$个差值使得他们的最大公因数大于$1$即可。我们可以将所有差值分解质因数,然后统计每个质因数出现的次数,再加上与$x$相等的数的个数就是$k$。统计$k$个时候顺便记录一下这些数的最大公因数即可。

    根据之前说的那个性质,我们随机出真答案的期望是$log$的。但是随机化这个东西...是靠脸的,我最开始用了那个$8$位质数做种子,然后调了$10$次,最后调了半天改成不用种子,随机$4$次。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::min; using std::max;
    using std::swap; using std::sort;
    using std::__gcd;
    typedef long long ll;
    
    template<typename T>
    void read(T &x) {
        int flag = 1; x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
        while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
    }
    
    const int N = 1e5 + 10, M = 1e7 + 10, _ = 1e6 + 10;
    int n, x, nk, nm, k, m, tot;
    int prime[_], save[M], s[_], g[_], v[N], c[N];
    bool notprime[M];
    
    int main () {
        for(int i = 2; i <= 10000000; ++i) {
            if(!notprime[i]) prime[++tot] = i, save[i] = tot;
            for(int j = 1; j <= tot && i * prime[j] <= 10000000; ++j) {
                notprime[i * prime[j]] = 1, save[i * prime[j]] = j;
                if(!(i % prime[j])) break;
            }
        } read(n);
        for(int i = 1; i <= n; ++i) read(v[i]);
        for(int T = 1; T <= 4; ++T) {
            x = v[rand() % n + 1], nk = s[0] = 0;
            for(int i = 1; i <= n; ++i) {
                c[i] = abs(v[i] - x);
                if(!c[i]) ++s[0];
            }
            for(int i = 1; i <= n; ++i) {
                int t = c[i];
                while(t && t != 1) {
                    int tmp = save[t];
                    ++s[tmp], g[tmp] = __gcd(g[tmp], c[i]);
                    if(nk < s[tmp] + s[0]) nk = s[tmp] + s[0], nm = 0;
                    if(nk == s[tmp] + s[0]) nm = max(nm, g[tmp]);
                    while(!(t % prime[tmp])) t /= prime[tmp];
                }
            }
            
            if(nk > k) k = nk, m = 0;
            if(nk == k) m = max(m, nm);
            for(int i = 1; i <= n; ++i) {
                int t = c[i];
                while(t && t != 1) {
                    int tmp = save[t];
                    s[tmp] = g[tmp] = 0;
                    while(!(t % prime[tmp])) t /= prime[tmp];
                }
            } 
        }printf("%d %d
    ", k, m);
        return 0;
    } 
    
  • 相关阅读:
    Codeforces Round #271 (Div. 2) F. Ant colony 线段树
    poj 1744 tree 树分治
    HDU Shell Necklace CDQ分治+FFT
    BZOJ 1567: [JSOI2008]Blue Mary的战役地图 矩阵二维hash
    BZOJ 1042: [HAOI2008]硬币购物 容斥+背包
    HDU 6078 Wavel Sequence 树状数组优化DP
    Gym
    HDU 6058 Kanade's sum 二分,链表
    HDU 6061 RXD and functions NTT
    ZOJ 3233 Lucky Number 容斥原理
  • 原文地址:https://www.cnblogs.com/water-mi/p/10247859.html
Copyright © 2011-2022 走看看