https://www.cnblogs.com/studyshare777/p/15026951.html
题意:
给n个数,让你找出一个最小的正整数m满足:这n个数%m得到的值各不相同。0<=a[i]<=500000。1<=n<=500000。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
const int N = 1500700;
const int MX = 500003;//偏移量要略大于5e5
const double PI = acos(-1);
struct Complex//复数类,自己定义常数小。
{
double x, y;
Complex operator+ (const Complex& t) const
{
return {x + t.x, y + t.y};
}
Complex operator- (const Complex& t) const
{
return {x - t.x, y - t.y};
}
Complex operator* (const Complex& t) const
{
return {x * t.x - y * t.y, x * t.y + y * t.x};
}
}a[N], b[N];
struct FFT
{
int rev[N], bit=0, tot=0;
void fft(Complex a[], int inv)
{
for (int i = 0; i < tot; i ++ )
if (i < rev[i])//按分治后的结果排序
swap(a[i], a[rev[i]]);
for (int mid = 1; mid < tot; mid <<= 1)
{
auto w1 = Complex({cos(PI / mid), inv * sin(PI / mid)});
for (int i = 0; i < tot; i += mid * 2)
{
auto wk = Complex({1, 0});
for (int j = 0; j < mid; j ++, wk = wk * w1)
{
auto x = a[i + j], y = wk * a[i + j + mid];
a[i + j] = x + y, a[i + j + mid] = x - y;
}
}
}
}
void work(){
int n=MX,m=MX;//注意具体数值----------------------------------
while ((1 << bit) < n + m + 1) bit ++;
tot = 1 << bit;
for (int i = 0; i < tot; i ++ )//预处理奇偶分组分治后的结果
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
fft(a, 1), fft(b, 1);//正向变换,系数表示变为点表示。
for (int i = 0; i < tot; i ++ ) a[i] = a[i] * b[i];//点表示法直接相乘
fft(a, -1);//逆向变换,点表示变成系数表示。
for (int i = 0; i <= n + m; i ++ )
a[i].x = (int)(a[i].x / tot + 0.5);
}
};
int p[N],vis[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>p[i];
for(int i=1;i<=n;i++){
a[p[i]].x=1;//+p[i]
b[MX-p[i]].x=1;//-p[i]///数组下标不允许负数,加了偏移量M
}
struct FFT solve;
solve.work();//p[i]和-p[i]乘积
for(int i=0;i<=MX;i++){
vis[i]=a[i+MX].x;//差值出现 0<=|ai-aj|<=500000 下标加上MX(偏移量)
}
int ans;
for(int i=1;i<=MX;i++){//枚举答案i
bool ok=1;
for(int j=i;j<=MX;j+=i){
//枚举i倍数,只要i不是任意差值的约数,i就是答案
if(vis[j]){
ok=0;break;
}
}
if(ok){
printf("%d\n",i);
break;
}
}
return 0;
}