题意
lyk有两序列a和b。
lyk想知道存在多少对x,y,满足以下两个条件。
1:gcd(x,y)=1。
2:
abx=bay
。
例如若a={1,1,1},b={1,1,1}。那么存在7对,因为除了x=2,y=2或x=3,y=3外都满足条件。
n<=100000,1<=a[i],b[i]<=n
分析
一开始没什么思路,后来看到评论有人说用反演可做,于是就会了。
按照反演套路,我们设f(d)表示gcd(x,y)=d其余条件不变的方案数,g(d)表示d|gcd(x,y)其余条件不变的方案数。显然我们要求的就是f(1)。如果求出g(d),那么就可以O(n)求出f(1)。而根据g(d)的定义,我们可以得到我们可以选的x或y必然满足d|x,那么就可以直接拿桶来统计了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=100005;
int n,a[N],b[N],t[N],tot,prime[N],mu[N];
LL f[N],g[N];
bool not_prime[N];
void get_prime(int n)
{
mu[1]=1;
for (int i=2;i<=n;i++)
{
if (!not_prime[i]) prime[++tot]=i,mu[i]=-1;
for (int j=1;j<=tot&&i*prime[j]<=n;j++)
{
not_prime[i*prime[j]]=1;
if (i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
}
int main()
{
scanf("%d",&n);
get_prime(n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) scanf("%d",&b[i]);
for (int d=1;d<=n;d++)
{
for (int i=d;i<=n;i+=d) t[b[a[i]]]++;
for (int i=d;i<=n;i+=d) g[d]+=t[a[b[i]]];
for (int i=d;i<=n;i+=d) t[b[a[i]]]=0;
}
LL ans=0;
for (int i=1;i<=n;i++) ans+=(LL)g[i]*mu[i];
printf("%lld",ans);
return 0;
}