CSP-J 2022 T1T2 《乘方》《解密》)

文章提供了两道CSP-J2022竞赛的题目解析。第一题要求计算不超过10^9的a^b值,若超出则输出-1。第二题涉及数学和逻辑,要求找到满足特定条件的正整数对(p_i,q_i),并处理无解情况。文章给出了解题思路和提示。
摘要由CSDN通过智能技术生成

题解不易,手下留赞


T1
T2

题面

[CSP-J 2022] 乘方

题目描述

小文同学刚刚接触了信息学竞赛,有一天她遇到了这样一个题:给定正整数 a a a b b b,求 a b a^b ab 的值是多少。

a b a^b ab b b b a a a 相乘的值,例如 2 3 2^3 23 即为 3 3 3 2 2 2 相乘,结果为 2 × 2 × 2 = 8 2 \times 2 \times 2 = 8 2×2×2=8

“简单!”小文心想,同时很快就写出了一份程序,可是测试时却出现了错误。

小文很快意识到,她的程序里的变量都是 int 类型的。在大多数机器上,int 类型能表示的最大数为 2 31 − 1 2^{31} - 1 2311,因此只要计算结果超过这个数,她的程序就会出现错误。

由于小文刚刚学会编程,她担心使用 int 计算会出现问题。因此她希望你在 a b a^b ab 的值超过 10 9 {10}^9 109 时,输出一个 -1 进行警示,否则就输出正确的 a b a^b ab 的值。

然而小文还是不知道怎么实现这份程序,因此她想请你帮忙。

输入格式

输入共一行,两个正整数 a , b a, b a,b

输出格式

输出共一行,如果 a b a^b ab 的值不超过 10 9 {10}^9 109,则输出 a b a^b ab 的值,否则输出 -1

样例 #1

样例输入 #1
10 9
样例输出 #1
1000000000

样例 #2

样例输入 #2
23333 66666 
样例输出 #2
-1

提示

对于 10 % 10 \% 10% 的数据,保证 b = 1 b = 1 b=1
对于 30 % 30 \% 30% 的数据,保证 b ≤ 2 b \le 2 b2
对于 60 % 60 \% 60% 的数据,保证 b ≤ 30 b \le 30 b30 a b ≤ 10 18 a^b \le {10}^{18} ab1018
对于 100 % 100 \% 100% 的数据,保证 1 ≤ a , b ≤ 10 9 1 \le a, b \le {10}^9 1a,b109

[CSP-J 2022] 解密

题目描述

给定一个正整数 k k k,有 k k k 次询问,每次给定三个正整数 n i , e i , d i n_i, e_i, d_i ni,ei,di,求两个正整数 p i , q i p_i, q_i pi,qi,使 n i = p i × q i n_i = p_i \times q_i ni=pi×qi e i × d i = ( p i − 1 ) ( q i − 1 ) + 1 e_i \times d_i = (p_i - 1)(q_i - 1) + 1 ei×di=(pi1)(qi1)+1

输入格式

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

接下来 k k k 行,第 i i i 行三个正整数 n i , d i , e i n_i, d_i, e_i ni,di,ei

输出格式

输出 k k k 行,每行两个正整数 p i , q i p_i, q_i pi,qi 表示答案。

为使输出统一,你应当保证 p i ≤ q i p_i \leq q_i piqi

如果无解,请输出 NO

样例 #1

样例输入 #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

提示

【数据范围】

以下记 m = n − e × d + 2 m = n - e \times d + 2 m=ne×d+2

保证对于 100 % 100\% 100% 的数据, 1 ≤ k ≤ 10 5 1 \leq k \leq {10}^5 1k105,对于任意的 1 ≤ i ≤ k 1 \leq i \leq k 1ik 1 ≤ n i ≤ 10 18 1 \leq n_i \leq {10}^{18} 1ni1018 1 ≤ e i × d i ≤ 10 18 1 \leq e_i \times d_i \leq {10}^{18} 1ei×di1018
1 ≤ m ≤ 10 9 1 \leq m \leq {10}^9 1m109

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

题解

第一题题解

针对第一题,先思考一下。
首先, a b a^b ab要小于 1 0 9 10^9 109,我们可以先把这个数算出来。
我估计有的小盆友会懵:
请添加图片描述
我会回答:
请添加图片描述
强算当然会炸,但题目让你答案小于 1 0 9 10^9 109在输出,这非常符合longlong类型的标准,也就是说,如果要你输出答案那一定不会炸longlong,在垒乘时,我们只需要特判,如果大于1e9,直接判掉。输出“No”,如下伪代码。

ret = 1;
// b和a就是题目里的b和a
for i : 1 to b then
	ret *= a;
	if ret > 1e9 then
		puts("-1");
		return 0; 

当然,最后只要输出ret就好了.

hint

a = 1 a = 1 a=1时,要特判,否则会当 b = 1 e 9 b = 1e9 b=1e9时,会TLE。

AC代码

// 以前写的代码,特丑。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string s;
signed main(){
    int a,b;
    cin >> a >> b;
    if (a == 1) cout << 1 << endl;
    else{
        int t = 1;
        for (int i = 1 ; i <= b ; i++){
            if (t > 1e9) {
                t = -1;
                break;
            }
            t *= a;
        }
        if (t > 1e9) t = -1;
        cout << t << endl;
    }
    return 0;
}

第二题题解

这道题呢,说实话,思维难度是有的,但不是特别大。
其实刚拿到这题时,有点无从下手。但细细一想,会发现并不难。
首先 ,对于每组数据,令 n = p i q i , p = p i , q = q i , e = e i , d = d i n = p_iq_i , p = p_i,q = q_i , e = e_i,d = d_i n=piqi,p=pi,q=qi,e=ei,d=di

这里, p i q i = p i × q i p_iq_i = p_i \times q_i piqi=pi×qi ,下文也是这样。

由题意得: { n = p q e d = ( p − 1 ) ( q − 1 ) + 1 \begin{cases} n = pq \\ ed = (p - 1)(q - 1) + 1 \end{cases} {n=pqed=(p1)(q1)+1

计算二式,得:
e d = p q − p − q + 1 + 1 = p q − p + 2 ed = pq - p - q + 1 + 1 = pq - p + 2 ed=pqpq+1+1=pqp+2
又 ∵ n = p q 又\because n = pq n=pq
∴ e d = n − p − q + 2 \therefore ed = n - p - q + 2 ed=npq+2
∴ 移项 , 得: e d + ( p + q ) = n + 2 \therefore 移项,得: ed + (p + q) = n + 2 移项,得:ed+(p+q)=n+2
∴ p + q = n − e d + 2 \therefore p + q = n - ed + 2 p+q=ned+2
令 m = n - ed + 2,

首先我们来学习(温习)一下,初一学过的知识(完全平方公式)。
( a + b ) 2 = a 2 + 2 a b + b 2 (a + b) ^ 2 = a^2 + 2ab + b^2 (a+b)2=a2+2ab+b2
( a − b ) 2 = a 2 − 2 a b + b 2 (a - b) ^ 2 = a^2 - 2ab + b^2 (ab)2=a22ab+b2
或者,去网上搜一下完全平方公式知二求二,自学一下。

∴ ( a + b ) 2 − ( a − b ) 2 = ( a 2 + 2 a b + b 2 ) − ( a 2 − 2 a b + b 2 ) = 4 a b \therefore (a + b) ^ 2 - (a - b) ^ 2 = (a^2 + 2ab + b^2) - (a^2 - 2ab + b^2) = 4ab (a+b)2(ab)2=(a2+2ab+b2)(a22ab+b2)=4ab
∴ p − q = ( p + q ) 2 − 4 p q \therefore p - q = \sqrt{(p + q)^2 - 4pq} pq=(p+q)24pq
连立两式,得: { p + q = n − e d + 2 = m p − q = ( p + q ) 2 − 4 p q \begin{cases} p + q = n - ed + 2 = m \\ p - q = \sqrt{(p + q)^2 - 4pq} \end{cases} {p+q=ned+2=mpq=(p+q)24pq

用m和n替换一下:

{ p + q = m p − q = m 2 − 4 n \begin{cases} p + q = m \\ p - q = \sqrt{m^2 - 4n} \end{cases} {p+q=mpq=m24n

又是一个小学的知识:和差问题,不会的某度自学。
{ 值大的式子 + 值小的式子 = 大的数的两倍 值大的式子 − 值小的式子 = 小的数的两倍 \begin{cases} \text{值大的式子 + 值小的式子 = 大的数的两倍} \\ {值大的式子 - 值小的式子 = 小的数的两倍} \end{cases} {值大的式子 + 值小的式子 = 大的数的两倍值大的式子值小的式子=小的数的两倍
举个例子
如上面: { p + q = m p − q = m 2 − 4 n \begin{cases} p + q = m \\ p - q = \sqrt{m^2 - 4n} \end{cases} {p+q=mpq=m24n
用一式去加二式,得: 2 p = m + m 2 − 4 n 2p = m + \sqrt{m^2 - 4n} 2p=m+m24n
用一式去减二式,得: 2 q = m − m 2 − 4 n 2q = m - \sqrt{m^2 - 4n} 2q=mm24n
∴ { p = m + m 2 − 4 n 2 q = m − m 2 − 4 n 2 \huge \therefore \begin{cases} p = \frac{m + \sqrt{m^2-4n}}{2} \\ q = \frac{m - \sqrt{m^2-4n}}{2}\end{cases} p=2m+m24n q=2mm24n

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define all(s) s.begin(),s.end()
#define endl "\n"
const int N = 5e5 + 5;
const int M = 1005;
signed main() {
    int T;
    scanf("%d",&T);
    while (T --) {
        ll n , e , d;
        scanf("%lld %lld %lld" , &n , &d , &e);
        ll m = n - e * d + 2;
        if (1ll * m * m < 4ll * n) {
            printf("NO\n");
            continue;
        }
        ll ret = sqrt(m * m - 4ll * n);
        if (ret * ret != m * m - 4ll * n) {
            printf("NO\n");
            continue;
        }
        ll p = (m + ret) / 2 , q = (m - ret) / 2;
        printf("%lld %lld\n" , q , p); 
    }
}

hint

m 2 < 4 n 或 m 2 − 4 n m^2 < 4n 或 m^2-4n m2<4nm24n不是一个完全平方数的时候,没有正整数解,也就是题目中的“NO”
还有,题目输出,先输出q,再输出p
T h e   e n d . \huge The \space end. The end.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值