给定 个整数 ,你可以选择两个 的正整数 ,然后将每一个 对 之中某一个取模得到 。
求 中最少有多少种不同的数值。
首先答案肯定要么是 要么是 ,因为我们可以对 取模。
若已经知道了两个通过取模同一个数 来得到 的 ,那么就可以知道 。而若取三个数 ,则至少有两个数是通过取模同一个数来得到 的。
所以只需要选出极差最小且两两不同的三个数,枚举它们两两的差值的因子做 ,检验是否合法即可。
检验某个 的时间复杂度是 的,所以时间复杂度是 ,其中 表示 内正整数的因子个数的最大值。
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define fio(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout);
const int S=200005;
int n,a[S];
inline int gcd(int x,int y)
{
if(x==0||y==0) return x+y;
int t=x%y;
while(t!=0) x=y,y=t,t=x%y;
return y;
}
inline bool chk2(int val,int x)
{
if(x==1) return false;
int rt=0,y=0;
for(int i=1;i<=n&&(y==0||(y>val&&y!=1));i++)
{
if(a[i]%x!=val)
{
if(a[i]<val) return false;
y=gcd(y,a[i]-val);
}
}
return y==0||(y>val&&y!=1);
}
inline bool chk(int val,int x)
{
if(x<2) return false;
for(int d=1;d*d<=x;d++)
{
if(x%d==0)
{
if(chk2(val%d,d)) return true;
if(d*d!=x&&chk2(val%(x/d),x/d)) return true;
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
n=unique(a+1,a+n+1)-a-1;
if(n<=2) return puts("1"),0;
int mn=0;
for(int i=3;i<=n;i++) if(mn==0||a[i]-a[i-2]<a[mn]-a[mn-2]) mn=i;
puts(
chk(a[mn],a[mn]-a[mn-1])||
chk(a[mn],a[mn]-a[mn-2])||
chk(a[mn-1],a[mn-1]-a[mn-2])
?"1":"2");
return 0;
}