为了解决本人DIV2 C题做的慢的问题,我决定每天切一到C题后写一篇题解。
题意:
给你一串数列,让你在数列后面加一个不同于前面任何一个数的数字,然后选取一个数对数列中的每个值一直加,直到数列中的所有值相同,求加这个数的最小次数。
思路:
首先我选的这个数肯定越大越好,这样可以尽可能减少我加的次数。于是我们对数组进行排序,然后遍历数组,找到后面一个数与前面一个数的差值,比如说3 5 9,我们得到5-3=2,9-5=4,然后发现此时我们选择2是最优的,所以我们就对每个差值取一个最大公约数,这就是要选取的值,然后最后插入的数字从最大的那个数开始遍历,只要有一个a[n]-i*(最大公约数)在原数列中没有出现过,那插入的数就是这个,最后取一下最大的数与前面每个数的差值之和,除一下最大公约数就是操作次数。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void fast() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);}
int a[200005];
int gcd(int x,int y)
{
if(y>x) swap(x,y);
int z=x%y;
if(z!=0) return gcd(y,z);
else return y;
}
signed main()
{
fast();
int t; cin>>t;
while(t--)
{
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
if(n==1) {cout<<1<<"\n"; continue;}
else
{
int sum=0;
int o=a[2]-a[1];
sum+=a[n]-a[1];
for(int i=2;i<n;i++)
{
o=gcd(o,a[i+1]-a[i]);
sum+=a[n]-a[i];
}
int ans=sum/o;
a[0]=0x3f3f3f3f;
int t=a[n]-o;
for(int i=n-1;i>=0;i--)
{
if(a[i]!=t)
{
ans+=n-i;
break;
}
t-=o;
}
cout<<ans<<"\n";
}
}
}