51nod 1675 序列变换 莫比乌斯反演(第二种形式)

来源:互联网 发布:淘宝专业术语大全 编辑:程序博客网 时间:2024/06/06 05:14

传送门:51nod 1675

题意:中文题。

思路:明明很像多校的一个题,还是简化版,而我愣是没想起来用莫比乌斯反演。。

这题用的是莫比乌斯反演的第二种转化形式:


设f[i]为最大公因数为i时的计数

F[i]为公因数包含i的时候的计数

显然满足第一个式子,因此我们就可以转化成二个式子求出f[1].

代码:

#include<stdio.h>#include<bits/stdc++.h>#define MAXN 100010using namespace std;int a[MAXN], b[MAXN], cnt[MAXN], mu[MAXN];long long F[MAXN];void mobius(int n) {       mu[1]=1;       for(int i=1;i<=n;i++)       for(int j=i+i;j<=n;j+=i)       mu[j]-=mu[i];}  int main(){int n;long long ans = 0;scanf("%d", &n);mobius(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 i = 1; i <= n; i++){for(int j = i; j <= n; j += i) cnt[a[b[j]]]++;for(int j = i; j <= n; j += i) F[i] += cnt[b[a[j]]];//将a[b[x]] == b[a[y]]的pair数量加到F[i]里(gcd(x, y) == i) for(int j = i; j <= n; j += i) cnt[a[b[j]]] = 0;}for(int i = 1; i <= n; i++) ans += mu[i] * F[i];//莫比乌斯反演求得f[1]cout << ans << endl;    return 0;}


阅读全文
0 0
原创粉丝点击