题意:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d9b94df69a93b6c11e56ad5c4cb05b05.png)
解法:
因为操作之后,序列的gcd很难维护.
考虑改成维护差分数组,b[i]=a[i]-a[i-1],
序列的gcd就是差分数组的gcd.
每次操作只有b[1]会改变,gcd(b[2],b[3]...b[n])是不变的,
设g=gcd(b[2],b[3]...b[n]),那么问题变为找到最小的k,满足gcd(b[1]+k,g)>1,
枚举g的因子p,计算使得b[1]+k是p的倍数的最小的k,然后用这个k更新答案即可.
code:
#include <bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int a[maxm];
int b[maxm];
int n;
int cas=1;
void solve(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
b[i]=a[i]-a[i-1];
}
printf("Case %d: ",cas++);
int g=0;
for(int i=2;i<=n;i++){
g=__gcd(g,b[i]);
}
if(g==0){
printf("%d\n",b[1]==1);
return ;
}
if(g==1){
puts("-1");
return ;
}
int ans=1e9;
for(int i=1;i*i<=g;i++){
if(g%i==0){
int x=i,y=g/i;
if(x>1){
int k=b[1]/x+(b[1]%x!=0);
ans=min(ans,k*x-b[1]);
}
if(y>1){
int k=b[1]/y+(b[1]%y!=0);
ans=min(ans,k*y-b[1]);
}
}
}
printf("%d\n",ans);
}
signed main(){
int T;scanf("%d",&T);
while(T--){
solve();
}
return 0;
}