博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Luogu P2257】YY 的 GCD
阅读量:4482 次
发布时间:2019-06-08

本文共 3464 字,大约阅读时间需要 11 分钟。

题目

求:

\[ \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 
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

你可能感兴趣的文章
JSP 标准标签库(JSTL)(JSP Standard Tag Library)
查看>>
导入项目遇到的问题: Some projects cannot be imported because they already exist in the workspace....
查看>>
华为:字符集合
查看>>
用Okhttp框架登录之后的Cookie设置到webView中(转)
查看>>
Java_Activiti5_菜鸟也来学Activiti5工作流_之入门简单例子(一)
查看>>
elasticsearch 5.x 系列之二 线程池的设置
查看>>
Java入门系列:实例讲解ArrayList用法
查看>>
洛谷P1080 国王游戏【大数】【贪心】
查看>>
Python 字符串相似性的几种度量方法
查看>>
OpenMP编程的任务调度控制
查看>>
卡特兰(Catalan)数列
查看>>
设计模式(一)工厂模式Factory(创建型)
查看>>
Warshall算法
查看>>
Python之匿名函数
查看>>
PhoneGap 3.0 安装
查看>>
每天一个小算法(2)----合并两个有序链表
查看>>
IOS开发把一个结构体放到数组中
查看>>
cglib动态代理(即AOP)
查看>>
08 H5新增input元素
查看>>
linux中安装软件的集中方法
查看>>