Description
给定一个长度为n的数组,可以对任意一个数取模(除数自定义,无约束)。求最少需要几步可以使得数组变成n的排列。
Solution
首先对于一个数\(a_i\)取模,得到的结果范围在\([0,\lfloor\frac{a_i-1}{2}\rfloor]\)且这个范围内的自然数都可以取到。
显然,已经在[1,n]之中的数直接使用更优。
所以我们可以进行贪心,从小到大将还需要取模的每个数映射到剩余的[1,n]中即可。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int a[N],s[N],t[N],n,m,n_s,n_t;
int main(){
int ti;
scanf("%d",&ti);
while(ti--){
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
n_s=n_t=0;
for(m=1;m<=n&&a[m]<=n;++m);
for(int i=1;i<m;++i){
if(a[i]==a[i-1]) s[++n_s]=a[i];
else for(int j=a[i-1]+1;j<a[i];++j) t[++n_t]=j;
}
for(int i=m;i<=n;++i) s[++n_s]=a[i];
for(int i=a[m-1]+1;i<=n;++i) t[++n_t]=i;
int ans=0;
for(int i=1;i<=n_t;++i){
if(t[i]*2<s[i]) ++ans;
else{
ans=-1;break;
}
}
printf("%d\n",ans);
}
return 0;
}