题目传送门

  传送门

  这个官方题解除了讲了个结论,感觉啥都没说,不知道是因为我太菜了,还是因为它真的啥都没说。

  如果 $x \geqslant y$,显然 gcd(x, y) 只会被调用一次。

  否则考虑每次操作前的数对应该是 $(y, y + kx)$。这样仍然不好处理。考虑忽略掉达到的 $a < b$ 的状态,那么每次的 $k \geqslant 1$。那么当较大数加上较小数的时候对应将 $k$ 加上 1,对应交换两边的数,然后将 $k$ 加上1。特别地,第一次操作不能做大加上小,因为第一次操作的时候没有 $k$。

  显然每次操作中,数对可以表示为 $(ax + by, cx + dy)$。那么一次加操作会得到 $(a + c) x , (c + d) y$,你发现这个东西和 SBT 的构造有点像。考虑把这个操作对应到 SBT 上。在两个相邻分数 $a, b$ 中插入一个分数 $c$ 可以得到新的两对 $a, c$ 和 $(c, b)$,分别可以看右加上左边以及左边加上右边。

  暂时不考虑 $m$ 的限制,我们来简单说明一下满足除了初始的数对一个数对可以对应 SBT 上某一层的一对相邻分数。考虑给出和上转化后的相同的生成方式。

  考虑第 $k$ 层中一对存在对应关系的相邻分数 $(p, q)$。

  如果 $p < q$,那么在树上的情况上是

  假设在 $p, q$ 间插入的分数为 $t$,根据 SBT 的构造方式可知 $q, t$ 是第 $(k + 1)$ 层的相邻分数 $t, p$ 是第 $(k + 1)$ 层的相邻分数。它们分别对应右加上左以及左加上右。当 $q < p$ 的时候是类似的。

  对于一个真分数 $\frac{a}{b}$,$xa + yb$ 的值总是比相应的它生成的两个分数的 $x'a + y'b$ 小 。一对相邻分数一定满足一个是另一个的祖先,这个不难使用归纳法证明。

  现在考虑加入 $m$ 的限制,那么真分数 $\frac{x}{y}$ 满足条件当且仅当 $x \leqslant y$ 以及 $xa + yb \leqslant m$,并且每一个满足条件的小于 $1$ 的真分数对应 $4$ 个满足条件的数对,特别地,1 如果合法只会对应 2 个满足条件的数对。

  前一个条件是因为第一次只能大加上小,第二个是因为题目限制。充分性由 SBT 构造过程和上面转化给出。

  那剩下的问题就非常傻逼了:

$$
\begin{align}
\sum_{i = 1}^{m} \sum_{j = 1}^{m} [i \leqslant j][(i, j) = 1][xi + yj \leqslant m]
\end{align}
$$

  基础莫比乌斯反演 & 类欧几里得即可计算。

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; #define ll long long ll ceil(ll a, ll b) {
return (a < 0) ? ((a - b + 1) / b) : (a / b);
} ll calc(ll a, ll b, ll c, ll n) {
if (!n) {
return 0;
}
if (!a) {
return ceil(b, c) * n;
}
if (b < 0 || b >= c || a < 0 || a >= c) {
ll ka = ceil(a, c), kb = ceil(b, c);
ll tmp = ka * ((n * (n - 1)) >> 1) + kb * n;
return calc(a - ka * c, b - kb * c, c, n) + tmp;
}
ll m = ((n - 1) * a + b) / c;
return n * m - calc(c, c - b + a - 1, a, m);
} const int C = 1e6 + 5;
const int D = 4e4 + 5; int pri[C];
int mu[C], smu[C]; void Euler(int n) {
static bitset<C> vis;
int num = 0;
mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!vis.test(i)) {
pri[num++] = i;
mu[i] = -1;
}
for (int *p = pri, *_ = pri + num, x; p != _ && (x = *p * i) <= n; p++) {
vis.set(x);
if (i % *p) {
mu[x] = -mu[i];
} else{
mu[x] = 0;
break;
}
}
}
for (int i = 1; i <= n; i++)
smu[i] = smu[i - 1] + mu[i];
} int T, N; int smu1[D];
boolean vis[D];
int S(int n) {
if (n <= 1000000)
return smu[n];
if (vis[N / n])
return smu1[N / n];
int &rt = smu1[N / n];
rt = 1;
vis[N / n] = true;
for (int i = 2, j; i <= n; i = j + 1) {
j = n / (n / i);
rt -= S(n / i) * (j - i + 1);
}
return rt;
} int main() {
scanf("%d%d", &T, &N);
Euler(1000000);
int x, y;
while (T--) {
scanf("%d%d", &x, &y);
if (x <= y) {
puts("1");
continue;
}
ll ans = 0;
for (int i = 1, j; i <= N / (x + y); i = j + 1) {
j = N / (N / i);
ans += (S(j) - S(i - 1)) * calc(-x - y, N / i - x - y, x, N / (i * (x + y)));
}
ans = ((ans << 1) + 1 + (x + y <= N)) << 1;
printf("%lld\n", ans);
}
return 0;
} 

算法马拉松35 E 数论只会Gcd - 类欧几里得 - Stern-Brocot Tree - 莫比乌斯反演的更多相关文章

  1. 数论只会GCD。。。

    一些关于GCD的代码.... #include <iostream> #include <cstdio> #include <cstring> using name ...

  2. LibreOJ β Round #2 E. 数论只会 GCD

    传送门 题解 题解里面说得很清楚了. 大约就是单独考虑每个数的贡献,然后看一下每个序列里有多少区间是没有这个数的,乘起来就好了. 为了处理修改我们需要每个值建一棵线段树来搞,但是窝zz了,写了线段树套 ...

  3. 51Nod1675 序列变换 数论 莫比乌斯反演

    原文http://www.cnblogs.com/zhouzhendong/p/8665675.html 题目传送门 - 51Nod1675 题意 给定序列$a,b$,让你求满足$\gcd(x,y)= ...

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

    第一次做莫比乌斯反演,推式子真是快乐的很啊(棒读) 前置 若函数\(F(n)\)和\(f(d)\)存在以下关系 \[ F(n)=\sum_{n|d}f(d) \] 则可以推出 \[ f(n)=\sum ...

  5. [luogu P2586] GCD 解题报告 (莫比乌斯反演|欧拉函数)

    题目链接:https://www.luogu.org/problemnew/show/P2568#sub 题目大意: 计算​$\sum_{x=1}^n\sum_{y=1}^n [gcd(x,y)==p ...

  6. Gcd HYSBZ - 2818 (莫比乌斯反演)

    Gcd \[ Time Limit: 10000 ms\quad Memory Limit: 262144 kB \] 题意 求 \(gcd\left(x,y\right) = p\) 的对数,其中\ ...

  7. 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛

    OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...

  8. 51Nod 算法马拉松21(迎新年)

    这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过 ...

  9. 「算法笔记」快速数论变换(NTT)

    一.简介 前置知识:多项式乘法与 FFT. FFT 涉及大量 double 类型数据操作和 \(\sin,\cos\) 运算,会产生误差.快速数论变换(Number Theoretic Transfo ...

随机推荐

  1. 如何在点击 a 标签的 onclick 时间时,不触发 window.onbeforeunload 事件

    如题! 直接贴代码了: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...

  2. WinForm 窗体间传递数据

    前言 做项目的时候,winfrom因为没有B/S的缓存机制,窗体间传递数据没有B/S页面传递数据那么方便,今天我们就说下winfrom中窗体传值的几种方式. 共有字段传递 共有字段传递实现起来很方便, ...

  3. Neo4j 第十二篇:使用Python驱动访问Neo4j

    neo4j官方驱动支持Python语言,驱动程序主要包含Driver类型和Session类型.Driver对象包含Neo4j数据库的详细信息,包括主机url.安全验证等配置,还管理着连接池(Conne ...

  4. Tomcat put上传漏洞_CVE2017-12615( JSP Upload Bypass/Remote Code Execution)

    CVE2017-12615漏洞复现( tomcat JSP Upload Bypass /Remote Code Execution) 一.漏洞原理 在windows服务器下,将readonly参数设 ...

  5. 第1篇Scrum冲刺博客

    目录 第1篇Scrum冲刺博客 各个成员在 Alpha 阶段认领的任务 各个成员的任务安排 整个项目预期的任务量 敏捷开发前的感想 团队期望 第1篇Scrum冲刺博客 各个成员在 Alpha 阶段认领 ...

  6. selenium和AutoIt工具辅助下载和上传

    上传 根据AutoIt Windows Info 所识别到的控件信息打开SciTE Script Editor编辑器,编写脚本. ;ControlFocus("title",&qu ...

  7. SQL Server学习内容(一)

    SQL Server SQL Server对大小写不敏感,每条语句末端使用分号. 1.SQL命令 SELECT 从数据中提取数据 UPDATE 更新数据中的数据 DELETE 从数据库中删除数据 IN ...

  8. linux的initcall机制

    linux的initcall机制(针对编译进内核的驱动) initcall机制的由来 我们都知道,linux对驱动程序提供静态编译进内核和动态加载两种方式,当我们试图将一个驱动程序编译进内核时,开发者 ...

  9. windows 下 创建项目的虚拟环境

    一. 为何使用虚拟环境 虚拟环境是Python解释器的一个私有副本,在这个环境你可以安装私有包,而且不会影响系统中安装的全局Python解释器. 在这个虚拟环境中的所有安装包,都是针对此环境的,不会被 ...

  10. CRT&EXCRT学习笔记

    非扩展 用于求解线性同余方程组 ,其中模数两两互质 . 先来看一看两个显然的定理: 1.若 x \(\equiv\) 0 (mod p) 且 y \(\equiv\) 0 (mod p) ,则有 x+ ...