思路:
对于
a
b
x
a_{b_x}
abx,可以看成一个新的序列
c
c
c,即:
a
b
1
,
a
b
2
,
a
b
3
.
.
.
<
=
=
>
c
1
,
c
2
,
c
3
.
.
.
.
a_{b_1},a_{b_2},a_{b_3} ... <==> c_1,c_2,c_3....
ab1,ab2,ab3...<==>c1,c2,c3....
对于 b a y b_{a_y} bay,同理可看成一个新的序列 d d d。
故问题等价于,求有多少对合法的下标
x
,
y
x,y
x,y,满足:
g
c
d
(
x
,
y
)
=
1
gcd(x,y) = 1
gcd(x,y)=1 且
c
x
=
d
y
c_x = d_y
cx=dy
这就是经典的莫比乌斯反演问题了。
设:
f
(
n
)
f(n)
f(n)为
g
c
d
(
x
,
y
)
=
n
gcd(x,y) = n
gcd(x,y)=n 且
c
x
=
d
y
c_x = d_y
cx=dy
而
F
(
n
)
F(n)
F(n)为
g
c
d
(
x
,
y
)
=
n
gcd(x,y) =n
gcd(x,y)=n的倍数 且
c
x
=
d
y
c_x = d_y
cx=dy
则:
F
(
n
)
=
∑
n
∣
d
f
(
d
)
<
=
=
>
f
(
n
)
=
∑
n
∣
d
μ
(
d
n
)
F
(
d
)
F(n) = \sum_{n|d}f(d) <==> f(n) = \sum_{n|d}\mu(\frac{d}{n})F(d)
F(n)=n∣d∑f(d)<==>f(n)=n∣d∑μ(nd)F(d)
故
f
(
1
)
=
∑
d
=
1
μ
(
d
)
F
(
d
)
f(1) = \sum_{d=1}\mu(d)F(d)
f(1)=d=1∑μ(d)F(d)
故可以枚举 d d d,对于 F ( d ) F(d) F(d)的求解,因为序列的取值是离散的,故需要暴力桶排求解。
代码:
#include<cmath>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int A = 1e5 + 10;
int mu[A],pri[A],a[A],b[A],cnt[A],tot;
bool vis[A];
void init(){
tot = 0;mu[1] = 1;
for(int i=2 ;i<A ;i++){
if(!vis[i]){
pri[++tot] = i;
mu[i] = -1;
}
for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){
vis[i*pri[j]] = 1;
if(i%pri[j] == 0){
mu[i*pri[j]] = 0;
break;
}
mu[i*pri[j]] = -mu[i];
}
}
}
int main(){
init();
int n;scanf("%d",&n);
for(int i=1 ;i<=n ;i++) scanf("%d",&a[i]);
for(int i=1 ;i<=n ;i++) scanf("%d",&b[i]);
ll ans = 0;
for(int i=1 ;i<=n ;i++){
ll res = 0;
for(int j=i ;j<=n ;j+=i) cnt[a[b[j]]]++;
for(int j=i ;j<=n ;j+=i) res += cnt[b[a[j]]];
for(int j=i ;j<=n ;j+=i) cnt[a[b[j]]]--;
ans += mu[i]*res;
}
printf("%I64d\n",ans);
return 0;
}