51nod1675-序列变换【莫比乌斯反演】

正题

题目连接:http://www.51nod.com/Challenge/Problem.html#problemId=1675


题目大意

给出两个长度为\(n\)的序列\(a,b\),求有多少对\(x,y\)满足

\[gcd(x,y)=1且a_{b_x}=b_{a_y} \]

\(1\leq n\leq 10^5,1\leq a_i,b_i\leq n\)


解题思路

额挺明显的一个莫反,枚举约数\(d\)的时候用一个数组统计一下有多少个\(a_{b_x}\)就好了。

时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,cnt,ans,a[N],b[N],c[N],mu[N],pri[N/10];
bool v[N];
void Prime(){
	mu[1]=1;
	for(ll i=2;i<=n;i++){
		if(!v[i])pri[++cnt]=i,mu[i]=-1;
		for(ll j=1;j<=cnt&&i*pri[j]<=n;j++){
			v[i*pri[j]]=1;
			if(i%pri[j]==0)break;
			mu[i*pri[j]]=-mu[i];
		}
	}
	return;
}
signed main()
{
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(ll i=1;i<=n;i++)scanf("%lld",&b[i]);
	Prime();
	for(ll i=1;i<=n;i++){
		ll sum=0;
		for(ll j=i;j<=n;j+=i)c[a[b[j]]]++;
		for(ll j=i;j<=n;j+=i)sum+=c[b[a[j]]];
		for(ll j=i;j<=n;j+=i)c[a[b[j]]]--;
		ans+=sum*mu[i];
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-08-01 17:38  QuantAsk  阅读(31)  评论(0编辑  收藏  举报