利用数的变形简化大规模问题#数论

判断是否存在正整数对 (x,y) 满足 x3−y3=N,若存在则输出其中一对,否则输出 -1。N<1e18;

核心公式变形:x3−y3=(x−y)(x2+xy+y2)=N由于 x>y≥1,可令 d=x−y(d≥1),则 x=y+d。代入后得:N=d⋅(3y2+3dy+d2)

因此,d 必须是 N 的约数,且满足:3y2+3dy+(d2−N/d)=0这是关于 y 的一元二次方程,可通过判别式判断是否存在正整数解。

解题步骤

  1. 枚举可能的 d:d 是 N 的约数,且 d≤3N(因 x3>N,故 x≤N1/3+1)。

  2. 检查约数条件:对每个 d,若 Nmodd!=0,直接跳过。

  3. 求解二次方程:令 m=N/d,方程化为 3y2+3dy+(d2−m)=0,计算判别式 Δ=12m−3d2。

  4. 验证正整数解:若 Δ 是完全平方数且 y 为正整数,则 x=y+d 是解。

    #include <iostream>
    #include <cmath>
    using namespace std;
    using ll = long long;

    int main() {
    ll N;
    cin >> N;

    复制代码
     // 枚举 d 的可能值,上限为 N^(1/3) + 2(避免遗漏)
     for (ll d = 1; d * d * d <= N + 2; ++d) {
         if (N % d != 0) continue; // d 必须是 N 的约数
         ll m = N / d;
    
         // 计算判别式 Δ = 12m - 3d²
         ll delta = 12 * m - 3 * d * d;
         if (delta < 0) continue; // 无实根
    
         // 检查 Δ 是否为完全平方数
         ll sqrt_delta = sqrt(delta);
         if (sqrt_delta * sqrt_delta != delta) continue;
    
         // 检查 y 是否为正整数:y = [-3d + sqrt(delta)] / 6
         if ((-3 * d + sqrt_delta) % 6 != 0) continue;
         ll y = (-3 * d + sqrt_delta) / 6;
         if (y <= 0) continue;
    
         // 找到有效解
         ll x = y + d;
         cout << x << " " << y << endl;
         return 0;
     }
    
     // 未找到解
     cout << -1 << endl;
     return 0;

    }

代码说明

  • 枚举范围:d 的上限设为 N1/3+2,因 x3≈N,故 x 不会远大于 N1/3,有效减少枚举量。
  • 判别式检查:确保二次方程有实根,且根为正整数。
  • 效率:时间复杂度为 O(N1/3),对 N≤1018 而言,N1/3≈106,枚举过程高效。

但是由于数据过大,在面对直接平方时很可能直接炸,使用二分法可以进行优化

复制代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

// 二分法求解二次方程ax² + bx + c = 0的非负整数解
// 原理:二次函数f(x)=ax²+bx+c开口向上(a=3>0),在正半轴单调递增,可用二分定位根
ll sol(ll a, ll b, ll c) {
    ll l = 0;               // 左边界:可能的最小解(0)
    ll r = 600000001;       // 右边界:足够大的上限(覆盖1e18范围内的可能解)
    // 二分查找:当区间长度大于1时继续缩小范围
    while (r - l > 1) {
        ll mid = (l + r) / 2;  // 中间值(避免溢出的写法)
        // 计算f(mid),若<=0说明根在右侧,移动左边界
        if (a * mid * mid + b * mid + c <= 0)
            l = mid;
        else  // 否则根在左侧,移动右边界
            r = mid;
    }
    // 检查左边界是否为方程的解(必须严格等于0)
    if (a * l * l + b * l + c == 0)
        return l;  // 找到有效解
    return -1;     // 无有效解
}

int main() {
    ll n;
    cin >> n;  // 输入目标值N

    // 枚举可能的d(d是x-y的差值,x = k + d,y = k)
    // d的上限为N^(1/3):因d³ <= N(否则方程左侧会超过N)
    for (ll d = 1; d * d * d <= n; ++d) {
        // d必须是N的约数(由立方差公式推导得出)
        if (n % d != 0)
            continue;
        
        // 计算m = N/d,将原方程转化为3k² + 3dk + (d² - m) = 0
        ll m = n / d;
        // 调用二分函数求解k,传入二次方程系数a=3, b=3d, c=d² - m
        ll k = sol(3, 3 * d, d * d - m);
        
        // 若k是正整数,则找到一组解(x,y)=(k+d, k)
        if (k > 0) {
            cout << k + d << " " << k << endl;
            return 0;  // 找到解后直接退出
        }
    }

    // 枚举完所有可能的d仍无有效解,输出-1
    cout << -1 << endl;
    return 0;
}
相关推荐
报错小能手4 小时前
计算机网络自顶向下方法10——应用层 HTTP/2 成帧 响应报文优先次序和服务器推
笔记·计算机网络
love530love4 小时前
【笔记】Podman Desktop 部署 开源数字人 HeyGem.ai
人工智能·windows·笔记·python·容器·开源·podman
CoookeCola4 小时前
开源图像与视频过曝检测工具:HSV色彩空间分析与时序平滑处理技术详解
人工智能·深度学习·算法·目标检测·计算机视觉·开源·音视频
DARLING Zero two♡4 小时前
【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐
java·数据结构·c++·算法·leetcode
CoovallyAIHub4 小时前
万字详解:多目标跟踪(MOT)终极指南
深度学习·算法·计算机视觉
胡萝卜3.04 小时前
C++面向对象继承全面解析:不能被继承的类、多继承、菱形虚拟继承与设计模式实践
开发语言·c++·人工智能·stl·继承·菱形继承·组合vs继承
蜗牛沐雨4 小时前
解决 OpenSSL 3.6.0 在 macOS 上 Conan 构建失败的链接错误
c++·macos
wudl55664 小时前
Apache Flink Keyed State 详解之一
算法·flink·apache
CoovallyAIHub5 小时前
Arm重磅加码边缘AI!Flexible Access开放v9平台,实现高端算力普惠
深度学习·算法·计算机视觉