莫比烏斯反演模板題
看到互質什麼的個數,,就想到莫比烏斯反演了吧,,
我們將f(n)設爲下標gcd剛剛爲n的組數,F(n)爲下標的gcd爲n的倍數的組數。。根據反演公式:
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<unordered_map>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<"q"<<endl;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<int,int> PII;
const double eps=1e-8;
const int P=1e9+7;
#define MX 1111111//最大範圍
int n,aa[MX],bb[MX],a[MX],b[MX];
int mu[MX],prime[MX];
bool isprime[MX];
void init()
{
mu[1]=1;
prime[0]=0;
mem(isprime,1);
for(int i=2; i<MX; i++)
{
if(isprime[i])prime[++prime[0]]=i,mu[i]=-1;
for(int j=1; j<=prime[0]&&i*prime[j]<MX; j++)
{
isprime[i*prime[j]]=0;
mu[i*prime[j]]=-mu[i];
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
}
}
}
int cnt[MX];
inline int read()
{
int ret=0,c,f=1;
for(c=getchar(); !(isdigit(c)||c=='-'); c=getchar());
if(c=='-') f=-1,c=getchar();
for(; isdigit(c); c=getchar()) ret=ret*10+c-'0';
if(f<0) ret=-ret;
return ret;
}
int main()
{
init();
FIN;
while(cin>>n)
{
for(int i=1; i<=n; i++)aa[i]=read();
for(int i=1; i<=n; i++)bb[i]=read();
for(int i=1; i<=n; i++)
{
a[i]=aa[bb[i]];
b[i]=bb[aa[i]];
}
LL ans=0;
for(int i=1; i<=n; i++)
if(mu[i])
{
LL t=0;
for(int j=i; j<=n; j+=i)cnt[a[j]]++;
for(int j=i; j<=n; j+=i)t+=cnt[b[j]];
for(int j=i; j<=n; j+=i)cnt[a[j]]--;
ans+=mu[i]*t;
}
cout<<ans<<endl;
}
return 0;
}