• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【更相减损术】洛谷 P10031 「Cfz Round 3」Xor with Gcd

前言

更相减损术简介

更相减损术是中国古代数学著作《九章算术》中记载的一种算法,主要用于求两个整数的最大公约数(GCD)。它比欧洲的欧几里得算法(辗转相除法)早了约300年,是中国数学史上的重要成就。

原理:两个整数的最大公约数等于其中较小的数和两数之差的最大公约数

公式:gcd(a, b) = gcd(min(a, b), |a - b|),其中 a ≥ b > 0

算法描述

  1. 输入两个正整数 a 和 b
  2. 如果 a = b,则a(或b)就是最大公约数
  3. 如果 a ≠ b,则用较大的数减去较小的数
  4. 将得到的差与较小的数作为新的 a 和 b
  5. 重复步骤 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;
}

posted on 2026-01-03 17:01  RomanLin  阅读(2)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3