【NOIP】模拟赛--绵阳南山中学#12(比赛密码MX-AK-SX)
T1
首先易得本题就是一个基环树森林,所以每个连通块最多只有一个环
<1>法一(本蒟蒻场上的写法):倍增O(t×nlog(n)),这里仅供参考
Details
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
int n, logn;
int idx[N], vis[N];
int rode[17][N];
void updata()
{
for( int i=logn;i>=0;i-- )
for( int j=1;j<=n;j++ )
if( rode[i][idx[j]] )
idx[j]=rode[i][idx[j]];
for( int i=1;i<=n;i++ )
vis[idx[i]]++;
}
void sovel()
{
cin>>n;
logn=log2( n );
for( int i=1;i<=n;i++ )
cin>>rode[0][i], idx[i]=i;
for( int pow=1;pow<=logn;pow++ )
for( int i=1;i<=n;i++ )
rode[pow][i]=rode[pow-1][rode[pow-1][i]];
updata();
ll ans=0;
for( int i=1;i<=n;i++ )
ans+=( n-i+1-vis[idx[i]] ), vis[idx[i]]--;
cout<<ans<<"\n";
}
int main()
{
freopen( "a.in","r",stdin );
freopen( "a.out","w",stdout );
ios::sync_with_stdio( false );
cin.tie( nullptr ), cout.tie( nullptr );
int t;
for( cin>>t;t;t-- )
sovel();
}
<2>法2:std的O(n)写法
如果两个点x,y它们走k步会到达同一个点上,则它们一定会先到一个环上
任取环上一个点,求到其他点的距离dis,设环长为c,则如果disx≡disy(modc)则点对(x,y)不满足条件
总的可能为Cn2那么对于每个联通块,假设有cnti个满足disx≡i(modc)的点x,将答案减去Ccnti2即可