2021牛客多校

时间:2021-07-19
本文章向大家介绍2021牛客多校,主要包括2021牛客多校使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Hash Function

题意

给一个数列长度为\(n\)的数列\(a\),找一个最小的\(seed\),使得数列\(a\)中所有数模\(seed\)后的值全都不一样。

题解

若数字\(x\)\(y\)\(seed\)后的值一样,假设\(x>y\),那么必定存在整数\(k\),使得\(y-x=k\times seed\)

所以,我们要找的那个\(seed\),不能是任何两个数的差值的因数,于是我们就需要预处理出任意两个数之间的差值的绝对值,朴素算法是\(n^2\)的,必定会超时,于是考虑\(FFT\)\(NTT\)

众所周知,离散域上的卷积的定义为

\[c_i=\sum_{j=0}^na_j \times b_{i-j} \]

其中向量\(c\)是向量\(a\)和向量\(b\)的卷积。

如何用卷积处理差值呢?在这里我们是\(a_j\)\(b_{i-j}\)乘,那么如果设\(a_i=1\)表示\(i\)这个差值存在,\(b_i\)同理,他们他俩相乘的结果不就表示他们下标对应的差值存在么?C++没有负下标,于是我们令\(b\)的下标从 \(5e^5\)开始即可,最后处理时,和\(5e^5\)取个差的绝对值就好了。

最后求值的时候用埃氏筛筛一下就行了。

AC代码

#include <bits/stdc++.h>

// #define IO ios::sync_with_stdio(NULL)
#define sc(z) scanf("%d", &(z))
#define _ff(i, a, b) for (ll i = a; i <= b; ++i)
#define _rr(i, a, b) for (ll i = b; i >= a; --i)
#define _f(i, a, b) for (ll i = a; i < b; ++i)
#define _r(i, a, b) for (ll i = b - 1; i >= a; --i)
#define mkp make_pair
#define endl "\n"
#define lowbit(x) x&(-x)
#define pb push_back

using namespace std;
typedef double db;
typedef long long ll;
typedef long double ld;

const int N = 2e6 + 5;
const int M = 1e6 + 5;
const ll mod = 1e9 + 7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int maxn = 500000;

struct Complext {
    db a, b;
    Complext(){}
    Complext(db r, db i):a(r),b(i){}
}a[N], b[N];

Complext operator + (Complext a, Complext b) { return Complext(a.a + b.a, a.b + b.b); }
Complext operator - (Complext a, Complext b) { return Complext(a.a - b.a, a.b - b.b); }
Complext operator * (Complext a, Complext b) { return Complext(a.a * b.a - a.b * b.b, a.a * b.b + a.b * b.a); }

int mp[M];
int lim = 1, len, rev[N];

void fft(Complext c[], db flag) {
    //int cnt = 0;
    _f(i, 0, lim) if (i < rev[i]) swap(c[i], c[rev[i]]);
    _f(i, 0, len) {
        int m = 1<<i;
        Complext wn = Complext(cos(pi / m), flag * sin(pi / m));
        for (int j = 0; j < lim; j += (m<<1)) {
            Complext w = Complext(1, 0);
            for (int k = 0; k < m; k++, w = w * wn) {
                Complext u = c[j + k], t = w * c[m + j + k];
                c[j + k] = u + t;
                c[m + k + j] = u - t;
                //cnt++;
            }
        }
    }
    if (flag == -1) _ff(i, 0, lim) a[i].a /= lim;
}

int main() {
    // IO;
    #ifndef ONLINE_JUDGE
    freopen("a.in", "r", stdin);
    // freopen("a.out", "w", stdout);
    #endif // !ONLINE_JUDGE

    int n, x; cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> x;
        a[x].a = 1;
        b[maxn - x].a = 1;
    }
    // while (lim <= maxn + maxn) lim <<= 1, len++;
    lim = 1<<20, len = 20;
    _f(i, 0, lim) rev[i] = (rev[i>>1]>>1)|((i&1)<<(len-1));
    fft(a, 1); fft(b, 1);
    _f(i, 0, lim) a[i] = a[i] * b[i];
    fft(a, -1);

    _f(i, 0, lim) {
        int tmp = (int)(a[i].a + 0.5);
        if (tmp > 0) mp[abs(i - maxn)] = 1;
    }

   // _ff(i, 1, 10) cout<<mp[i]<<" ";cout<<endl;

    _ff(i, n, maxn+1) {
        int flag = 1;
        for (int j = i; j <= maxn+1; j += i) {
            if (mp[j]) {
                flag = 0;
                break;
            }
        }
        if (flag) {
            cout << i << endl;
            break;
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/xdaniel/p/15029622.html