历年CSP-J第二轮题目

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;
}

P8815 [CSP-J2022] 逻辑表达式

P8816 [CSP-J2022] 上升点列

猜你喜欢

转载自blog.csdn.net/u013313909/article/details/127588804