CSP-J2022
P8813 [CSP-J2022] 乘方
#include <bits/stdc++.h>
using namespace std;
int a, b;
long long ans=1; //可能会爆int
int main()
{
scanf("%d %d", &a, &b);
if(a==1){ //避免TLE, 因为b可以到10^9
printf("1");
return 0;
}
for(int i=1; i<=b; ++i){
ans*=a;
if(ans>1e9){
printf("-1");
return 0;
}
}
printf("%lld", ans);
return 0;
}
P8814 [CSP-J2022] 解密
暴力部分分
//暴力部分分
#include <bits/stdc++.h>
using namespace std;
int k;
bool flag;
long long n, e, d, p, q, delta, sqr;
int main()
{
scanf("%d", &k);
while(k--){
scanf("%lld %lld %lld", &n, &d, &e);
flag=false;
for(int p=1; p<=sqrt(n); ++p){
if(n%p!=0){
continue;
}
q=n/p;
if(e*d==(p-1)*(q-1)+1){
printf("%lld %lld\n", p, q);
flag=true;
break;
}
}
if(!flag){
printf("NO\n");
}
}
return 0;
}
方法1:数学推导,求根公式
#include <bits/stdc++.h>
using namespace std;
int k;
long long n, e, d, p, q, delta, sqr;
int main()
{
scanf("%d", &k);
//p*p+(e*d-n-2)*p+n=0
while(k--){
scanf("%lld %lld %lld", &n, &d, &e);
delta=(e*d-n-2)*(e*d-n-2)-4*n;
sqr=sqrt(delta);
//无解、无整数解
if(delta<0 || sqr*sqr!=delta || ((n+2-e*d)-sqr)%2!=0 || ((n+2-e*d)+sqr)%2!=0){
printf("NO\n");
continue;
}
p=((n+2-e*d)-sqr)/2;
q=((n+2-e*d)+sqr)/2;
if(p<0 || q<0){
printf("NO\n");
continue;
}
printf("%lld %lld\n", p, q);
}
return 0;
}
方法2:二分
#include <bits/stdc++.h>
using namespace std;
int k;
long long n, e, d, p, q, l, r, mid, asd;
int main()
{
scanf("%d", &k);
//ed=pq-p-q+2, p+q固定, p越小, pq越小, n=pq
//ed=n-p-q+2, p+q=n-ed+2
while(k--){
scanf("%lld %lld %lld", &n, &d, &e);
asd=n-e*d+2;
l=1, r=asd/2; //r=sqrt(n);也行
while(l<r){
mid=(l+r)>>1;
//p小了,得往大
if(mid*(asd-mid)<n){
l=mid+1;
}
else{ //p大了, 得往小
r=mid;
}
}
if(n%l==0 && l*(asd-l)==n){
printf("%lld %lld\n", l, n/l);
}
else{
printf("NO\n");
}
}
return 0;
}
二分错误代码
#include <bits/stdc++.h>
using namespace std;
int k;
long long n, e, d, p, q, l, r, mid;
int main()
{
scanf("%d", &k);
//ed=pq-p-q+2, pq固定, p越小, p+q越大, pq-p-q+2越小
while(k--){
scanf("%lld %lld %lld", &n, &d, &e);
l=1, r=sqrt(n);
//错误原因, 无法确保n%mid为0,从而无法确保(mid-1)*(n/mid-1)+1的准确性
while(l<r){
mid=(l+r)>>1;
//p小了,得往大
if((mid-1)*(n/mid-1)+1<e*d){
l=mid+1;
}
else{ //p大了, 得往小
r=mid;
}
}
if(n%l==0 && (l-1)*(n/l-1)+1==e*d){
printf("%lld %lld\n", l, n/l);
}
else{
printf("NO\n");
}
}
return 0;
}