题目传送门

  传送门

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

  如果 $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. Kubernetes 远程工具连接k8s集群

    Kubernetes 远程工具连接k8s集群 1.将Master的kubectl文件复制到Node内 scp k8s/kubernetes/server/bin/kubectl root@192.16 ...

  2. 以STM32和FPGA为核心的多组件协调工作系统

  3. 3-Consul 使用手册

    原文:http://www.liangxiansen.cn/2017/04/06/consul/ Consul包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键 ...

  4. jsonHelper帮助类

    使用前,需引用开源项目类using Newtonsoft.Json 链接:https://pan.baidu.com/s/1htK784XyRCl2XaGGM7RtEg 提取码:gs2n using ...

  5. 小鸟初学Shell编程(八)环境变量、预定义变量与位置变量

    环境变量 环境变量:每个Shell打开都可以获得到的变量. 我们知道通过export的方式打开可以让子进程读取父进程的变量的值,那怎么样才能让每一个进程都能读取到变量的值呢? 在这呢,系统有一些默认的 ...

  6. Docker install in Linux

    install command sudo yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-man ...

  7. DesignPattern系列__07合成复用原则

    基本介绍 合成复用原则的核心,就是尽量去使用组合.聚合等方式,而不是使用继承. 核心思想 1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起. 2.针对接口编程,而不是 ...

  8. window10 蓝牙怎么连接音响或蓝牙耳机

    window10 蓝牙怎么连接音响或蓝牙耳机 1.在电脑上依次点击win图标右键-->设置,打开系统设置窗口. 2.点击“设备”,在窗口左侧选择“蓝牙”,右侧检查并开启电脑的蓝牙设备开关, 3. ...

  9. java--正则校验

    java--正则校验 // boolearn matches(String regex):判断当前字符串是否匹配指定的正则表达式true/false demo: String qq = "1 ...

  10. MES助力日立电梯提升精细化管理水平

    项目背景介绍 日立电梯在2008年到2012年期间分别在五地工厂(上海.广州.天津.成都.扶梯)上线了ERP系统,在后续的使用时间里,逐渐发现现有ERP系统对于生产现场管理,产品质量追溯,产能控制等方 ...