【Project Euler】530 GCD of Divisors 莫比乌斯反演

【题目】GCD of Divisors

【题意】给定f(n)=Σd|n gcd(d,n/d)的前缀和F(n),n=10^15。

【算法】莫比乌斯反演

【题解】参考:任之洲数论函数.pdf

这个范围显然杜教筛也是做不了的,而且考虑直接化简f(n)也遇到了困难,所以考虑将前缀和的Σ一起化简

$$F(n)=\sum_{i=1}^{n}\sum_{d|i}(d,\frac{i}{d})$$

这一步很常见的是第一重改为枚举倍数,但这样化简后面就推不下去了。

这道题必须最后转成$\sigma_0(n)$才能解出来。

所以直接枚举gcd值

$$F(n)=\sum_{d=1}^{n}d\sum_{i=1}^{n}\sum_{g|i}[(g,\frac{i}{g})=d]$$

这里gcd(g,i/g)=d,说明i中必须至少包含2个d,那么令i=i/d^2,g即可任取i的因子,最终的g和i/g各乘d即可,所以可以进行如下化简。(关键①)

$$F(n)=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d^2}}\sum_{g|i}[(g,\frac{i}{g})=1]$$

转化成φ希望不大,所以直接莫比乌斯反演。

$$F(n)=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d^2}}\sum_{g|i}\sum_{d‘|g \cap d‘|\frac{i}{g}}\mu(d‘)$$

$$F(n)=\sum_{d=1}^{n}\sum_{d‘=1}^{n}d*\mu(d‘)\sum_{i=1}^{\frac{n}{d^2}}\sum_{g|i}[d‘|g \cap d‘|\frac{i}{g}]$$

这里和上面一样,都是要求d‘|g&&d‘|i/g,因此从i中提取2个d‘,即令i=i/d‘^2。

$$F(n)=\sum_{d=1}^{n}\sum_{d‘=1}^{n}d*\mu(d‘)\sum_{i=1}^{\frac{n}{(dd‘)^2}}\sum_{g|i}1$$

会发现后面是约数个数。(关键②)

$$F(n)=\sum_{d=1}^{n}\sum_{d‘=1}^{n}d*\mu(d‘)\sum_{i=1}^{\frac{n}{(dd‘)^2}}\sigma_0(i)$$

前面部分发现d*μ(d‘)好像可以卷积到φ,考虑合并dd‘来构造卷积,令d=dd‘。(关键③)

$$F(n)=\sum_{d=1}^{\sqrt{n}}\sum_{g|d}g*\mu(\frac{n}{g})\sum_{i=1}^{\frac{n}{(dd‘)^2}}\sigma_0(i)$$

这里d只枚举到√n,因为d>√n时后面的Σ=0,没有贡献。

然后根据狄利克雷卷积μ*id=φ可以化简

$$F(n)=\sum_{d=1}^{\sqrt{n}}\varphi(d)\sum_{i=1}^{\frac{n}{(dd‘)^2}}\sigma_0(i)$$

大功告成!

其中,约数个数的前缀和可以进行分块取值优化,如下

$$\sum_{i=1}^{n}\sigma_0(i)=\sum_{i=1}^{n}\sum_{d|i}1=\sum_{i=1}^{n}\sum_{j=1}^{\frac{n}{i}}1$$

$$\sum_{i=1}^{n}\sigma_0(i)=\sum_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor$$

然后线性筛φ的过程中求解即可。

复杂度分析:

$$\sum_{i=1}^{\sqrt{n}}O(\sqrt{\frac{n}{i^2}})=\sum_{i=1}^{\sqrt{n}}O(\frac{\sqrt{n}}{i})=O(\sqrt{n} ln \sqrt{n})$$

倒数第二步将√n提到最外面,Σ内就是调和数列,和近似为ln n。

#include<cstdio>
#include<cmath>
#define int long long
const int maxn=32000000;
int phi[maxn],n,prime[maxn],tot;
int solve(int n){
    int pos,sum=0;
    for(int i=1;i<=n;i=pos+1){
        pos=n/(n/i);
        sum+=(pos-i+1)*(n/i);
    }
    return sum;
}
#undef int
int main(){
#define int long long
    scanf("%lld",&n);
    int ans=1*solve(n),N=(int)sqrt(n)+1;phi[1]=1;//1
    for(int i=2;i<=N;i++){
        if(!phi[i])phi[prime[++tot]=i]=i-1;
        for(int j=1;j<=tot&&i*prime[j]<=N;j++){
            if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
        ans+=phi[i]*solve(n/(i*i));
    }
    printf("%lld",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/onioncyc/p/8488255.html

时间: 2024-07-30 14:58:30

【Project Euler】530 GCD of Divisors 莫比乌斯反演的相关文章

bnu——GCD SUM (莫比乌斯反演)

题目:GCD SUM 题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=39872 算法:莫比乌斯反演.优化 1 #include<stdio.h> 2 #define N 100001 3 typedef long long LL; 4 bool pri[N]={0}; 5 int prim[N],po=0; 6 int mu[N]; 7 LL f[N],ff[N]; //缩短时间 8 /* 9 莫比乌斯函数mu[i]的定义: 10 1. 如

51nod 1594 Gcd and Phi(莫比乌斯反演)

题目链接 传送门 思路 如果这题是这样的: \[ F(n)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\phi(gcd(i,j)) \] 那么我们可能会想到下面方法进行反演: \[ \begin{aligned} F(n)=&\sum\limits_{k=1}^{n}\phi(k)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[gcd(i,j)=k]&\=&\sum\limits_{k=1}^{n}\p

SPOJ - PGCD Primes in GCD Table(莫比乌斯反演)

http://www.spoj.com/problems/PGCD/en/ 题意: 给出a,b区间,求该区间内满足gcd(x,y)=质数的个数. 思路: 设f(n)为 gcd(x,y)=p的个数,那么F(n)为 p | gcd(x,y)的个数,显然可得F(n)=(x/p)*(y/p). 这道题目因为可以是不同的质数,所以需要枚举质数, 但是这样枚举太耗时,所以在这里令t=pk, 这样一来的话,我们只需要预处理u(t/p)的前缀和,之后像之前的题一样分块处理就可以了. 1 #include<ios

SPOJDIVCNT2: Counting Divisors(莫比乌斯反演)

http://acm.tzc.edu.cn/acmhome/vProblemList.do?method=problemdetail&oj=SPOJ&pid=DIVCNT2 给出n求 其中是除数函数,0代表0次方. 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define

project euler做题记录

ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{array}{c} S(n) & = & \sum_{i = 1} ^ n \sum_{p = 1} ^ i \sum_{q = p + 1} ^ i \frac {1}{pq}[p + q \geq i][gcd(p, q) = 1] \& = & \sum_{i = 1} ^

hdu_1695: GCD 【莫比乌斯反演】

题目链接 这题求[1,n],[1,m]gcd为k的对数.而且没有顺序. 设F(n)为公约数为n的组数个数 f(n)为最大公约数为n的组数个数 然后在纸上手动验一下F(n)和f(n)的关系,直接套公式就好了.注意要删去重复的. 关于 莫比乌斯反演 的结论 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e6; int prime[maxn+5]; bool check[maxn+

HDU 1695 (莫比乌斯反演) GCD

题意: 从区间[1, b]和[1, d]中分别选一个x, y,使得gcd(x, y) = k, 求满足条件的xy的对数(不区分xy的顺序) 分析: 虽然之前写过一个莫比乌斯反演的总结,可遇到这道题还是不知道怎么应用. 这里有关于莫比乌斯反演的知识,而且最后的例题中就有这道题并给出了公式的推导. 1 #include <cstdio> 2 #include <algorithm> 3 typedef long long LL; 4 5 const int maxn = 1000000

hdu-1695 GCD(莫比乌斯反演)

题目链接: GCD Time Limit: 6000/3000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor

BZOJ 2818 Gcd (莫比乌斯反演 或 欧拉函数)

2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2534  Solved: 1129 [Submit][Status][Discuss] Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sample Output 4 HINT hint 对于样例(2,2),(2,4),(3,3),(4,2)