【Luogu P2257】YY 的 GCD

题目

求:

\[
\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) \in \mathbb P]
\]

有 \(T\) 组数据, \(T\le 10^4, n, m\le 10^7\)

分析

莫比乌斯反演:

\[
\begin{align*}
& \sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) \in \mathbb P]\ = & \sum_{p \in \mathbb P, p\le \min(n, m)}\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = p]\\end{align*}
\]

设 \(f(x) = \sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = x]\), $F(x) = \sum_{i = 1}^n \sum_{j = 1}^m [x?|\gcd(i, j)]=\left\lfloor \frac nx\right\rfloor\left\lfloor \frac mx\right\rfloor $

则有:
\[
F(x) = \sum_{x|d, d\le \min(n, m)} f(d) \Rightarrow f(x) = \sum_{x|d, d\le\min(n, m)} \mu(\frac dx)F(d)
\]
故有:
\[
\begin{align*}
& \sum_{p \in \mathbb P, p\le \min(n, m)}\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = p]\ = & \sum_{p \in \mathbb P, p\le \min(n, m)} f(p) \ = & \sum_{p \in \mathbb P, p\le \min(n, m)} \sum_{p|d,d\le \min(n, m)} \mu(\frac dp) \left\lfloor \frac nd\right\rfloor\left\lfloor \frac md\right\rfloor \ = & \sum_{d = 1}^{\min(n, m)} \sum_{p \in \mathbb P,p|d, p\le \min(n, m)} \mu(\frac dp) \left\lfloor \frac nd\right\rfloor\left\lfloor \frac md\right\rfloor \ = & \sum_{d = 1}^{\min(n, m)} \left\lfloor \frac nd\right\rfloor\left\lfloor \frac md\right\rfloor \sum_{p \in \mathbb P,p|d, p\le \min(n, m)} \mu(\frac dp)
\end{align*}
\]
设 $g(x) = \sum_{p \in \mathbb P,p|x, p\le \min(n, m)} \mu(\frac xp) $

求法(暴力出奇迹, 经测试下面算法耗时不到 \(0.5 s\)):

void get_g(int n) {
    for(int i = 1; i <= n; i++) {
        int tmp = i;
        while(tmp != 1) {
            g[i] += mobius[i / s_factor[tmp]];
            int p = s_factor[tmp];
            if(tmp % (p * p) == 0) break;
            for(; tmp % p == 0; tmp /= p);
        }
        g_prefix[i] = g_prefix[i - 1] + g[i];
    }
}

有上式等于:
\[
\sum_{d = 1}^{\min(n, m)} \left\lfloor \frac nd\right\rfloor\left\lfloor \frac md\right\rfloor g(d)
\]
对于 \(\left\lfloor \frac nd\right\rfloor\left\lfloor \frac md\right\rfloor\) 相同的值整除分块即可.

代码

#include <bits/stdc++.h>

typedef long long Int64;

const int kMaxSize = 1e7 + 5;

int s_factor[kMaxSize], prime[kMaxSize], mobius[kMaxSize], g[kMaxSize],
    g_prefix[kMaxSize], prime_tot = 0;
bool isn_prime[kMaxSize];

void euler_sieve(int n) {
    mobius[1] = 1;
    isn_prime[0] = isn_prime[1] = true;
    for(int i = 2; i <= n; i++) {
        if(!isn_prime[i]) {
            prime[prime_tot++] = i;
            s_factor[i] = i;
            mobius[i] = -1;
        }
        for(int j = 0; j < prime_tot && i * prime[j] <= n; j++) {
            isn_prime[i * prime[j]] = true;
            s_factor[i * prime[j]] = prime[j];
            mobius[i * prime[j]] = -mobius[i];
            if(i % prime[j] == 0) {
                mobius[i * prime[j]] = 0;
                break;
            }
        }
    }
}

void get_g(int n) {
    for(int i = 1; i <= n; i++) {
        int tmp = i;
        while(tmp != 1) {
            g[i] += mobius[i / s_factor[tmp]];
            int p = s_factor[tmp];
            if(tmp % (p * p) == 0) break;
            for(; tmp % p == 0; tmp /= p);
        }
        g_prefix[i] = g_prefix[i - 1] + g[i];
    }
}

int main() {
    euler_sieve(1e7);
    get_g(1e7);
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, m;
        Int64 ans = 0;
        scanf("%d%d", &n, &m);
        if(!n) break;
        for(int l = 1, r; l <= n && l <= m; l = r + 1) {
            r = std::min(n / (n / l), m / (m / l));
            ans += (Int64)(n / l) * (m / l) * (g_prefix[r] - g_prefix[l - 1]);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhylj/p/10229884.html

时间: 2024-10-13 23:25:12

【Luogu P2257】YY 的 GCD的相关文章

[题解]luogu P2257 YY的GCD

袁野的gcd 首先可以肯定的是这是一道数论题 所以题目就是: \(\sum_{i=1}^N \sum_{j=1}^M [gcd(i,j)\in prime]\) 接下来就可以愉快的推式子了~ 首先可以按套路枚举 prime 和 gcd \(\sum_{p \in prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)=p]\) 所以我们显然可以将\(i\)和\(j\) 同时除以 \(p\),得到 \(\sum_{p\in prime}\sum_{i=1}^{N}\sum_

luogu P2257 YY的GCD

嘟嘟嘟 感觉这几道数论题都差不多,但这到明显是前几道的升级版. 推了一大顿只能得60分,不得不看题解. 各位看这老哥的题解吧 我就是推到他用\(T\)换掉\(kd\)之前,然后枚举\(T\)的.这个转换确实想不出来啊. 还有最后一句,最终的式子 \[\sum_{T = 1} ^ {n} \lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor * \sum_{k | T} \mu(\frac{T}{k}) (k \in prime)\] 他把

P2257 YY的GCD(莫比乌斯反演)

P2257 YY的GCD luogu题解第一篇非常棒,当然你也可以point here(转) 正题因为题解写的太优秀所以没得补充 这里用了一个卡常技巧:循环展开 就是以代码长度为代价减少循环次数 实测快了15ms(一个点1.5ms....) (用了快读更慢???(大雾)但是register真有用) #include<iostream> #include<cstdio> #include<cstring> #include<cctype> #define re

P2257 YY的GCD

P2257 YY的GCD 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 输入输出格式 输入格式: 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示N, M 输出格式: T行,每行一个整数表示第i组数据的结果 输入输出样例 输入样例#1: 复制 2 10 10 100 100 输出样例#1: 复制 30 2791

P2257 YY的GCD (莫比乌斯反演)

[题目链接] https://www.luogu.org/problemnew/show/P2257 // luogu-judger-enable-o2 /* ----------------------- [题解] https://www.luogu.org/blog/peng-ym/solution-p2257 [莫比乌斯反演] http://www.cnblogs.com/peng-ym/p/8647856.html [整除分块] http://www.cnblogs.com/peng-y

bzoj 2820 luogu 2257 yy的gcd (莫比乌斯反演)

题目大意:求$gcd(i,j)==k,i\in[1,n],j\in[1,m] ,k\in prime,n,m<=10^{7}$的有序数对个数,不超过10^{4}次询问 莫比乌斯反演入门题 为方便表述,由于n和m等价,以下内容均默认n<=m 题目让我们求:$\sum_{k=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==k]$ 容易变形为:$\sum_{k=1}^{n}\sum_{i=1}^{\left \lfloor \frac{n}{k} \righ

P2257 YY的GCD (莫比乌斯反演)

题意:求\[\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j) = prim]\] 题解:那就开始化式子吧!! \[f(d) = \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j) = d]\] \[F(x) = \sum_{d|x} f(d) = \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{x} \right \rfloor\] \[f(d) = \sum_{d|

洛谷【P2257】YY的GCD

YY的GCD 原题链接 这应该是我做的第一道莫比乌斯反演的题目. 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 输入输出格式 输入格式: 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示N, M 输出格式: T行,每行一个整数表示第i组数据的结果 说明 T=10000,N, M <= 10000000 解

【BZOJ 2820】 YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 807  Solved: 404 [Submit][Status] Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 Input 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示

bzoj 2820: YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种 傻×必然不会了,于是向你来请教……多组输入 Input 第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M Output T行,每行一个整数表示第i组数据的结果 Sample Input