题解 CF347B 【Fixed Points】
第一种方法:
暴力枚举
dai码
#include<bits/stdc++.h>
using namespace std;
long long n,m,l;
int a[100000],s[100000],d[100000],ans;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
if(i==a[i])
{
s[i]=1;
ans++;
}
}
int q=0;
for(int i=1;i<=n;i++)
{
for(int j=1+i;j<=n;j++)
{
if(!s[i]&&!s[j])
{
if(a[i]==j)
{
q=max(q,1);
}
if(a[j]==i)
{
q=max(q,1);
}
if(a[j]==i&&a[i]==j)q=2;
}
}
}
ans+=q;
cout<<ans;
return 0;
}
然后你会发现:
没错它T了。
于是第二种方法诞生了:
暴力枚举的复杂度是$O(n^2)$,明显行不通。
那么我们为什么要去找$j$呢?
我们直接用$a_i$去找$a_{a_i}$不就好了?
正确的代码
#include<bits/stdc++.h>
using namespace std;
long long n,m,l;
int a[100000],s[100000],d[100000],ans;
int main()
{
cin>>n;
for(int i=0;i<n;i++)//因为是从零开始数,所以下标是0
{
cin>>a[i];
if(i==a[i])//如果i=a[i],则标记并ans+1
{
s[i]=1;
ans++;
}
}
int q=0;
for(int i=1;i<=n;i++)
{
if(!s[i]&&!s[a[i]])//如果第i和第a[i]个数没被标记
{
if(a[a[i]]==i)q=2;//如果第a[i]个数的值等于i则代表互换ans+2,否则ans+1
else q=max(q,1);//防止q=2被覆盖
}
}
ans+=q;\\因为只能换一次所以取q最大值
cout<<ans;
return 0;
}