2022 解密 · 方案一 二分求整数平方根
化成一元二次方程,二分开方没有浮点误差
正文
// CSP-J 2022 复赛 T2 · 解密
// 原题:https://oj.yecheng.tv/p/CSPJ2022B
// 题意:每组给 n、d、e,要找正整数 p、q 使得
// n = p * q 且 e * d = (p - 1)(q - 1) + 1
// 把第二式展开:e*d = p*q - p - q + 2,代入 p*q = n,得到
// p + q = n - e*d + 2
// 于是问题变成「已知两数之和 m 与两数之积 n,求这两个数」,解一元二次方程:
// p、q 是 x^2 - m*x + n = 0 的两根,判别式 delta = m^2 - 4*n = (p - q)^2。
// 所以 delta 必须是一个完全平方数,且 (m - sqrt(delta)) 还得是偶数。
//
// 方案一 · 二分求整数平方根(完全避开浮点误差)
// 自己写 isqrt(x):返回不超过 sqrt(x) 的最大整数,用二分实现,
// 比较时写成 mid <= x / mid 而不是 mid * mid <= x,这样连溢出都一起躲掉了。
// n 能到 1e18,但题目保证 m = n - e*d + 2 不超过 1e9,
// 所以 m * m 最多 1e18,long long(约 9.2e18)装得下。
#include <bits/stdc++.h>
using namespace std;
long long isqrt(long long x) {
long long l = 0, r = 1000000000LL; // sqrt(1e18) 正好是 1e9
while (l < r) {
long long mid = (l + r + 1) / 2;
if (mid <= x / mid) l = mid; // mid^2 <= x,用除法比较不溢出
else r = mid - 1;
}
return l;
}
int main() {
freopen("decode.in", "r", stdin);
freopen("decode.out", "w", stdout);
int k;
cin >> k;
while (k--) {
long long n, d, e;
cin >> n >> d >> e;
long long m = n - e * d + 2; // 这就是 p + q
long long delta = m * m - 4 * n; // 这就是 (p - q)^2
if (delta < 0) {
cout << "NO\n";
continue;
}
long long s = isqrt(delta);
if (s * s != delta) { // 判别式不是完全平方数,无整数解
cout << "NO\n";
continue;
}
if ((m - s) % 2 != 0) { // 除以 2 要能整除
cout << "NO\n";
continue;
}
long long p = (m - s) / 2;
long long q = (m + s) / 2;
if (p >= 1 && p * q == n) cout << p << " " << q << "\n";
else cout << "NO\n";
}
return 0;
}
CSP-J 标程 · 复赛真题的其它内容
- 2019 数字游戏 · 方案一 逐字符统计
- 2019 数字游戏 · 方案二 二进制位运算
- 2020 优秀的拆分 · 方案一 贪心从大到小减
- 2020 优秀的拆分 · 方案二 直接看二进制位
- 2021 分糖果 · 方案一 枚举每个 k
- 2021 分糖果 · 方案二 看余数在哪一段
- 2022 乘方 · 方案一 边乘边判断
- 2022 乘方 · 方案二 快速幂加封顶
- 2023 小苹果 · 方案一 照规则真模拟
- 2023 小苹果 · 方案二 只盯住两个数字
- 2024 扑克牌 · 方案一 用集合去重
- 2024 扑克牌 · 方案二 二维布尔表
- 2025 拼数 · 方案一 收集后降序排序
- 2025 拼数 · 方案二 桶计数
- 2019 公交换乘 · 方案一 暴力匹配
- 2019 公交换乘 · 方案二 时间窗口优化
- 2020 直播获奖 · 方案一 每轮排序
- 2020 直播获奖 · 方案二 桶计数
- 2021 插入排序 · 方案一 每次真排一遍
- 2021 插入排序 · 方案二 增量维护有序表
- 2022 解密 · 方案二 先估后校开方
- 2023 公路 · 方案一 朴素贪心
- 2023 公路 · 方案二 单调栈预处理
- 2024 地图探险 · 方案一 四方向分支写
- 2024 地图探险 · 方案二 方向数组
- 2025 座位 · 方案一 把座位表填出来
- 2025 座位 · 方案二 直接算排名
- 2019 纪念品 · 方案一 逐天完全背包
- 2019 纪念品 · 方案二 砍掉不赚钱物品
- 2020 表达式 · 方案一 每次重算后缀式
- 2020 表达式 · 方案二 建树加关键性传播
- 2021 网络连接 · 方案一 手写解析
- 2021 网络连接 · 方案二 读入后回拼校验
- 2022 逻辑表达式 · 方案一 递归分治
- 2022 逻辑表达式 · 方案二 递归下降
- 2023 一元二次方程 · 方案一 照公式逐步写
- 2023 一元二次方程 · 方案二 拆成小函数
- 2024 小木棍 · 方案一 先定位数再贪心
- 2024 小木棍 · 方案二 预处理最小数字表
- 2025 异或和 · 方案一 贪心能接就接
- 2025 异或和 · 方案二 动态规划加值域数组
- 2019 加工零件 · 方案一 递归加记忆化
- 2019 加工零件 · 方案二 奇偶最短路
- 2020 方格取数 · 方案一 深搜回溯
- 2020 方格取数 · 方案二 按列动态规划
- 2021 小熊的果篮 · 方案一 每轮扫一遍
- 2021 小熊的果篮 · 方案二 链表加有序集合
- 2022 上升点列 · 方案一 先只考虑不加点
- 2022 上升点列 · 方案二 二维动态规划
- 2023 旅游巴士 · 方案一 分层图加优先队列
- 2023 旅游巴士 · 方案二 状态压成一维
- 2024 接龙 · 方案一 按定义广搜
- 2024 接龙 · 方案二 滑动窗口逐轮推进
- 2025 多边形 · 方案一 枚举所有子集
- 2025 多边形 · 方案二 排序加计数 DP