一定要读懂题啊,各位acmer!!!!
这道题说了要将不是1~n的数字模到1~n里面去,所以原数组属于这个范围的就不用判断了,直接跳过,顺便将其记录下来,以便筛选1~n中没有出现的数,并让不在1~n范围的数字去模成它们。在这里我们需要知道一个定理:一个数n,模上所有数后的取值范围是 0~ (n - 1)/ 2.所以将1~n以及待模的数从小到大排序,将大于n的数存到vecotr里(以下简称v),让v里最小的数,使其 (v - 1) / 2 与此时1~n种最小的没有出现的数i相比,如果 (v - 1) /2 < i,说明这个v无法模成i,自然后面的i它也摸不到,即使后面的v都能模成对应的i,但是总是不会让1~n这个数组填满,所以不存在,输出-1。如果每次判断都成功,那么直接输出v.size()即可。见代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
void solve()
{
int n;
cin >> n;
vector<int> v;
map<int, bool> st;
for(int i = 0; i < n; i ++)
{
int a;
cin >> a;
if(!st[a] && a <= n) st[a] = true;
else v.push_back(a);
}
sort(v.begin(), v.end());
int cnt = 0;
for(int i = 1; i <= n; i ++)
{
if(!st[i])
{
if((v[cnt] - 1) / 2 < i)
{
cout << -1 << endl;
return;
}
else cnt ++;
}
}
cout << v.size() << endl;
return ;
}
int main()
{
int t;
cin >> t;
while(t --)
{
solve();
}
return 0;
}