前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ2818: Gcd(莫比乌斯反演)

BZOJ2818: Gcd(莫比乌斯反演)

作者头像
attack
发布2018-07-27 15:25:34
2240
发布2018-07-27 15:25:34
举报

题意

求$gcd(i, j)$为素数的对数,$ i \leqslant N ,j \leqslant N$

Sol

一开以为要用zap那题的思路暴力求,但是化到一半发现会做了qwq。

设$p_i$为第$i$个素数

我们要求的是

$$ans = \sum_{i = 1}^n \sum_{j = 1}^n [gcd(i, j) = p_i]$$

$$ = \sum_{i = 1}^{\frac{n}{p_i}} \sum_{j = 1}^{\frac{n}{p_i}} [gcd(i, j) = 1]$$

根据定理

$$\sum_{i = 1}^n \sum_{j = 1}^n [gcd(i, j) = 1] = 2\phi(i) - 1$$

而且$10^7$以内的质数只有大约$6 * 10^5$个

直接对$\phi$做前缀和然后暴力算就行了

代码语言:javascript
复制
// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long 
#define rg register 
//#define int long long 
using namespace std;
const int MAXN = 1e7 + 10, mod = 1e9 + 7;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int prime[MAXN], vis[MAXN], tot;
LL phi[MAXN];
void GetPhi(int N) {
    vis[1] = phi[1] = 1;
    for(rg int i = 2; i <= N; i++) {
        if(!vis[i]) prime[++tot] = i, phi[i] = i - 1;
        for(rg int j = 1; j <= tot && i * prime[j] <= N; j++) {
            vis[i * prime[j]] = 1;
            if(!(i % prime[j])) {phi[i * prime[j]] = phi[i] * prime[j]; break;}
            phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
    for(rg int i = 2; i <= N; i++) phi[i] += phi[i - 1];
}
inline LL F(int N) {
    return (phi[N] << 1) - 1;
}
int main() {
    GetPhi(1e7 + 5);
    int N = read();
    LL ans = 0;
    for(rg int i = 1; i <= tot && prime[i] <= N; i++) 
        ans += F(N / prime[i]);
    printf("%lld\n", ans);
    return 0;
}
/*

*/
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题意
  • Sol
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档