《P8814 [CSP-J 2022] 解密》

**摘要:**本题给定 k 次询问,每次给出三个正整数 n、e、d,要求求出两个正整数 p、q,使其满足 n=p×q 且 e×d=(p−1)(q−1)+1。通过数学推导可将问题转化为求解一元二次方程,利用判别式判断是否有整数解,并借助二分或开方运算高效求解,最终输出满足条件的 p、q 或 NO。

题目描述

给定一个正整数 k,有 k 次询问,每次给定三个正整数 ni​,ei​,di​,求两个正整数 pi​,qi​,使 ni​=pi​×qi​、ei​×di​=(pi​−1)(qi​−1)+1。

输入格式

第一行一个正整数 k,表示有 k 次询问。

接下来 k 行,第 i 行三个正整数 ni​,di​,ei​。

输出格式

输出 k 行,每行两个正整数 pi​,qi​ 表示答案。

为使输出统一,你应当保证 pi​≤qi​。

如果无解,请输出 NO。

输入输出样例

输入 #1复制

复制代码
10
770 77 5
633 1 211
545 1 499
683 3 227
858 3 257
723 37 13
572 26 11
867 17 17
829 3 263
528 4 109

输出 #1复制

复制代码
2 385
NO
NO
NO
11 78
3 241
2 286
NO
NO
6 88

说明/提示

【样例 #2】

见附件中的 decode/decode2.in 与 decode/decode2.ans。

【样例 #3】

见附件中的 decode/decode3.in 与 decode/decode3.ans。

【样例 #4】

见附件中的 decode/decode4.in 与 decode/decode4.ans。

【数据范围】

以下记 m=n−e×d+2。

保证对于 100% 的数据,1≤k≤105,对于任意的 1≤i≤k,1≤ni​≤1018,1≤ei​×di​≤1018 ,1≤m≤109。

测试点编号 k≤ n≤ m≤ 特殊性质
1 103 103 103 保证有解
2 103 103 103 无
3 103 109 6×104 保证有解
4 103 109 6×104 无
5 103 109 109 保证有解
6 103 109 109 无
7 105 1018 109 保证若有解则 p=q
8 105 1018 109 保证有解
9 105 1018 109 无
10 105 1018 109 无

附件下载

decode.zip1.74KB

代码实现:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int k;
    scanf("%d", &k);
    while(k--){
        ll n, d, e;
        scanf("%lld %lld %lld", &n, &d, &e);
        ll m = n - e * d + 2; 
		 __int128 delta = (__int128)m * m - (__int128)4 * n;
        if(delta < 0){
            printf("NO\n");
            continue;
        }
        ll s = (ll)sqrtl((long double)delta);
        while((__int128)s * s < delta) s++;
        while((__int128)s * s > delta) s--;
        if((__int128)s * s != delta){
            printf("NO\n");
            continue;
        }
        if((m - s) % 2 != 0 || (m - s) <= 0){
            printf("NO\n");
            continue;
        }
        ll p = (m - s) / 2;
        ll q = (m + s) / 2;
        if(p <= 0 || q <= 0 || p * q != n){
            printf("NO\n");
            continue;
        }
        printf("%lld %lld\n", p, q);
    }
    return 0;
}