[CSP-J 2022] 乘方
题目背景
由于众所周知的原因,官方数据现置于子任务 0,剩余的子任务为民间数据。
题目描述
小文同学刚刚接触了信息学竞赛,有一天她遇到了这样一个题:给定正整数 aaa 和 bbb,求 aba^bab 的值是多少。
aba^bab 即 bbb 个 aaa 相乘的值,例如 232^323 即为 333 个 222 相乘,结果为 2×2×2=82 \times 2 \times 2 = 82×2×2=8。
“简单!”小文心想,同时很快就写出了一份程序,可是测试时却出现了错误。
小文很快意识到,她的程序里的变量都是 int
类型的。在大多数机器上,int
类型能表示的最大数为 231−12^{31} - 1231−1,因此只要计算结果超过这个数,她的程序就会出现错误。
由于小文刚刚学会编程,她担心使用 int
计算会出现问题。因此她希望你在 aba^bab 的值超过 109{10}^9109 时,输出一个 -1
进行警示,否则就输出正确的 aba^bab 的值。
然而小文还是不知道怎么实现这份程序,因此她想请你帮忙。
输入格式
输入共一行,两个正整数 a,ba, ba,b。
输出格式
输出共一行,如果 aba^bab 的值不超过 109{10}^9109,则输出 aba^bab 的值,否则输出 -1
。
样例 #1
样例输入 #1
10 9
样例输出 #1
1000000000
样例 #2
样例输入 #2
23333 66666
样例输出 #2
-1
提示
对于 10%10 \%10% 的数据,保证 b=1b = 1b=1。
对于 30%30 \%30% 的数据,保证 b≤2b \le 2b≤2。
对于 60%60 \%60% 的数据,保证 b≤30b \le 30b≤30,ab≤1018a^b \le {10}^{18}ab≤1018。
对于 100%100 \%100% 的数据,保证 1≤a,b≤1091 \le a, b \le {10}^91≤a,b≤109。
解题思路
通过while循环将b个a相乘即可,但是由于数据“1≤a,b≤1091 \le a, b \le {10}^91≤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,剩余的子任务为民间数据。
题目描述
给定一个正整数 kkk,有 kkk 次询问,每次给定三个正整数 ni,ei,din_i, e_i, d_ini,ei,di,求两个正整数 pi,qip_i, q_ipi,qi,使 ni=pi×qin_i = p_i \times q_ini=pi×qi、ei×di=(pi−1)(qi−1)+1e_i \times d_i = (p_i - 1)(q_i - 1) + 1ei×di=(pi−1)(qi−1)+1。
输入格式
第一行一个正整数 kkk,表示有 kkk 次询问。
接下来 kkk 行,第 iii 行三个正整数 ni,di,ein_i, d_i, e_ini,di,ei。
输出格式
输出 kkk 行,每行两个正整数 pi,qip_i, q_ipi,qi 表示答案。
为使输出统一,你应当保证 pi≤qip_i \leq q_ipi≤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+2m = n - e \times d + 2m=n−e×d+2。
保证对于 100%100\%100% 的数据,1≤k≤1051 \leq k \leq {10}^51≤k≤105,对于任意的 1≤i≤k1 \leq i \leq k1≤i≤k,1≤ni≤10181 \leq n_i \leq {10}^{18}1≤ni≤1018,1≤ei×di≤10181 \leq e_i \times d_i \leq {10}^{18}1≤ei×di≤1018
,1≤m≤1091 \leq m \leq {10}^91≤m≤109。
测试点编号 | k≤k \leqk≤ | n≤n \leqn≤ | m≤m \leqm≤ | 特殊性质 |
---|---|---|---|---|
111 | 10310^3103 | 10310^3103 | 10310^3103 | 保证有解 |
222 | 10310^3103 | 10310^3103 | 10310^3103 | 无 |
333 | 10310^3103 | 10910^9109 | 6×1046\times 10^46×104 | 保证有解 |
444 | 10310^3103 | 10910^9109 | 6×1046\times 10^46×104 | 无 |
555 | 10310^3103 | 10910^9109 | 10910^9109 | 保证有解 |
666 | 10310^3103 | 10910^9109 | 10910^9109 | 无 |
777 | 10510^5105 | 101810^{18}1018 | 10910^9109 | 保证若有解则 p=qp=qp=q |
888 | 10510^5105 | 101810^{18}1018 | 10910^9109 | 保证有解 |
999 | 10510^5105 | 101810^{18}1018 | 10910^9109 | 无 |
101010 | 10510^5105 | 101810^{18}1018 | 10910^9109 | 无 |
解题思路(方法一)
显而易见,我们可以通过暴力打出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+qm=p+qm=p+q,最后转化为解x2−mx+n=0x^2-mx+n=0x2−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;
}