【更相减损术】洛谷 P10031 「Cfz Round 3」Xor with Gcd
前言
更相减损术简介
更相减损术是中国古代数学著作《九章算术》中记载的一种算法,主要用于求两个整数的最大公约数(GCD)。它比欧洲的欧几里得算法(辗转相除法)早了约300年,是中国数学史上的重要成就。
原理:两个整数的最大公约数等于其中较小的数和两数之差的最大公约数
公式:gcd(a, b) = gcd(min(a, b), |a - b|),其中 a ≥ b > 0
算法描述
- 输入两个正整数 a 和 b
- 如果 a = b,则a(或b)就是最大公约数
- 如果 a ≠ b,则用较大的数减去较小的数
- 将得到的差与较小的数作为新的 a 和 b
- 重复步骤 2-4,直到两数相等
案例
以求解 84 与 36 的最小公约数为例,下面是更相减损术的计算过程:
题目
https://www.luogu.com.cn/problem/P10031
题解
输入一个正整数 \(n\),求 \(gcd(1, n) \oplus gcd(2, n) \oplus ⋯ \oplus gcd(n, n)\) 的结果,\(1\leq n \leq10^{18}\)。
由更相减损术可知:
- \(gcd(i, n)=gcd(n-i, i)\)
- \(gcd(n-i,n)=gcd(i,n-i)\)
那么可推知:\(gcd(i,n)=gcd(n-i, n)\)。
又因为一个数异或自身等于 \(0\),因此:
- 当 \(n\) 为奇数时,\(gcd(1, n) \oplus gcd(2, n) \oplus ⋯ \oplus gcd(n, n) = gcd(n, n) = n\)
- 当 \(n\) 为偶数时,\(gcd(1, n) \oplus gcd(2, n) \oplus ⋯ \oplus gcd(n, n) = gcd(n/2,n) \oplus gcd(n, n) = n/2 \oplus n\)
参考代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
ll n;
int T;
void solve() {
cin >> n;
ll ans = n & 1 ? n : n ^ n / 2;
cout << ans << '\n';
}
int main() {
IOS
cin >> T;
while (T --) {
solve();
}
return 0;
}
浙公网安备 33010602011771号