[CSP-J 2022] 乘方
题目背景
由于众所周知的原因,官方数据现置于子任务 0,剩余的子任务为民间数据。
题目描述
小文同学刚刚接触了信息学竞赛,有一天她遇到了这样一个题:给定正整数 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
231−1,因此只要计算结果超过这个数,她的程序就会出现错误。
由于小文刚刚学会编程,她担心使用 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
b≤2。
对于
60
%
60 \%
60% 的数据,保证
b
≤
30
b \le 30
b≤30,
a
b
≤
10
18
a^b \le {10}^{18}
ab≤1018。
对于
100
%
100 \%
100% 的数据,保证
1
≤
a
,
b
≤
10
9
1 \le a, b \le {10}^9
1≤a,b≤109。
解题思路
通过while循环将b个a相乘即可,但是由于数据“ 1 ≤ a , b ≤ 10 9 1 \le a, b \le {10}^9 1≤a,b≤109”,所以1的1e9次方会超时(虽然官方测试样例没有1),所以要特殊考虑,。
代码展示
#include <bits/stdc++.h>
using namespace std;
int main(){
long long a,b;//记得开long long
cin>>a>>b;
long long ans=1;
if(a==1)
cout<<1<<endl;
else{
bool f=true;
for(int i=1;i<=b;i++){
ans*=a;
if(ans>1e9){
cout<<-1<<endl;
f=false;
break;
}
}
if(f)
cout<<ans<<endl;
}
return 0;
}
[CSP-J 2022] 解密
题目背景
由于众所周知的原因,官方数据现置于子任务 0,剩余的子任务为民间数据。
题目描述
给定一个正整数 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=(pi−1)(qi−1)+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 pi≤qi。
如果无解,请输出 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
提示
【样例 #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 m = n - e \times d + 2 m=n−e×d+2。
保证对于
100
%
100\%
100% 的数据,
1
≤
k
≤
10
5
1 \leq k \leq {10}^5
1≤k≤105,对于任意的
1
≤
i
≤
k
1 \leq i \leq k
1≤i≤k,
1
≤
n
i
≤
10
18
1 \leq n_i \leq {10}^{18}
1≤ni≤1018,
1
≤
e
i
×
d
i
≤
10
18
1 \leq e_i \times d_i \leq {10}^{18}
1≤ei×di≤1018
,
1
≤
m
≤
10
9
1 \leq m \leq {10}^9
1≤m≤109。
测试点编号 | 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 | 无 |
解题思路(方法一)
显而易见,我们可以通过暴力打出60分
代码展示(方法一)
#include <bits/stdc++.h>
using namespace std;
unsigned long long k,n,e,d;
int main(){
cin>>k;
for(int i=1;i<=k;i++){
cin>>n>>e>>d;
unsigned long long p,q;
bool f=false;
for(int j=1;j*j<=n;j++){
if(n%j==0){
q=n/j;
if(e*d==(j-1)*(q-1)+1){
f=true;
p=j;
break;
}
}
}
if(f)
cout<<p<<" "<<q<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
解题思路(方法二)
根据题目,我们可以推出 p + q = n − e ∗ d + 2 = m , p + q = n − e ∗ d + 2 = m, p+q=n−e∗d+2=m,所以 m = p + q m=p+q m=p+q,最后转化为解 x 2 − m x + n = 0 x^2-mx+n=0 x2−mx+n=0这个方程。
代码展示(方法二)
#include <bits/stdc++.h>
using namespace std;
long long k,n,e,d;
int main(){
cin>>k;
for(int i=1;i<=k;i++){
cin>>n>>e>>d;
long long m=n-e*d+2;
long long f=m*m-4*n;
if(f>=0){
long long ff=sqrt(f);
if(ff*ff==f&&(m-ff)%2==0){
cout<<(m-ff)/2<<" "<<(m+ff)/2<<endl;
continue;
}
}
cout<<"NO"<<endl;
}
return 0;
}