zoukankan      html  css  js  c++  java
  • [牛客多校]第一场H.Hash Function

    题意:定义哈希函数(h_{seed}(x) = x mod{seed}),给定一个集合,要求找到一个最小的(seed),使得集合内的数字哈希函数两两不同。
    数据范围:(nle 5 imes 10^5, a_ile 5 imes 10^5)

    注意到两个数字的哈希函数当且仅当$seed | (a_i - a_j) (,假如我们知道每一个)(a_i -a _j)(是否存在,我们枚举每个)seed(,然后判断)seed(的每个倍数是否存在,这个过程是)O(nlogn)$的,因为调和级数。

    于是问题变成怎么快速求出每个((a_i - a_j))是否存在。

    (f(i))表示(i)是否存在,反转整个数组,变成(g(x) = f(500000 - x)),然后跟原数组卷积,我们发现卷积(h(x) = sum f(i) * f(50000 - x - i))(f(i),f(50000 - x - i))都不为(0)的时候对数组有贡献,表示存在这样的一个((a_i - a_j))

    于是NTT随便卷一下就行了。

    #include <bits/stdc++.h>
    #define pt(x) cout << x << endl;
    #define Mid ((l + r) / 2)
    #define lson (rt << 1)
    #define rson (rt << 1 | 1)
    using namespace std;
    int read() {
    	char c; int num, f = 1;
    	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    	return f * num;
    }
    const int P = 998244353, G = 3, Gi = 332748118;
    const int N = 5e5, M = N * 5 + 1009;
    int n, A[M], B[M];
    int Pow(int a, int p) {
    	int ans = 1;
    	for( ; p; p >>= 1, a = 1ll * a * a % P)
    		if(p & 1)
    			ans = 1ll * a * ans % P;
    	return ans % P;
    }
    namespace Polynomial {
    	const double Pi = acos(-1.0);
    	int rev[M];
    	template <typename T>
    	void change(T *y, int n) {
    		for(int i = 0; i < n; i++) 
    			rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
    		for(int i = 0; i < n; i++) 
    			if(i < rev[i])
    				swap(y[i], y[rev[i]]);
    	}
    	void NTT(int *A, int n, int type) {
    		//type = 1 DFT 
    		//type = -1 IDFT 
    		change(A, n);
    		for(int m = 1; m < n; m <<= 1) {
    			int Wn = Pow(type == 1 ? G : Gi, (P - 1) / (m << 1));
    			for(int i = 0; i < n; i += 2 * m) {
    				int w = 1;
    				for(int j = 0; j < m; j++, w = 1ll * w * Wn % P) {
    					int x = A[i + j], y = 1ll * w * A[i + j + m] % P;
    					A[i + j] = (x + y) % P;
    					A[i + j + m] = (x - y + P) % P;
    				} 
    			}
    		}
    		if(type == -1) {
    			int inv = Pow(n, P - 2);
    			for(int i = 0; i < n; i++)
    				A[i] = 1ll * A[i] * inv % P;
    		}
    	}
    	
    }
    int check(int x) {
    	for(int i = x; i <= N; i += x) 
    		if(A[i]) 
    			return false;
    	return true;
    }
    signed main()
    {
    	n = read();
    	for(int i = 1; i <= n; i++) {
    		int x = read();
    		A[x] = 1;
    		B[N - x] = 1;
    	}
    	int lim = 1;
    	while(lim <= 2 * N) lim <<= 1;
    	Polynomial :: NTT(A, lim, 1); 
    	Polynomial :: NTT(B, lim, 1);
    	for(int i = 0; i < lim; i++) A[i] = 1ll * A[i] * B[i] % P;
    	Polynomial :: NTT(A, lim, -1); 
    	reverse(A, A + 1 + N);
    	int i = n;
    	while(1) {
    		if(check(i)) {
    			printf("%d
    ", i);
    			return 0;
    		}
    		i++;
    	}
    	return 0;
    }
    
  • 相关阅读:
    saltstack学习
    linux命令学习(2):wc 命令
    linux命令学习(1):grep 命令
    Docker Compose—简化复杂容器应用的利器
    Docker-compose命令详解
    Python json数据写入csv json excel文件
    Centos 不重启 修改ulimit参数
    pip包管理工具 基本使用
    python 使用xpath解析含有命名空间(xmlns)的xml
    pyqt5 + pyinstaller 制作爬虫小程序
  • 原文地址:https://www.cnblogs.com/onglublog/p/15291627.html
Copyright © 2011-2022 走看看