解密

题目来源

CSP2022-J-T1:http://oj.tfls.net/d/lnzt/p/14

题解一:

枚举:同鸡兔同笼
根据题意:n=p*q e*d-1=(p-1)*(q-1)
根据数据规模可知,枚举2~sqrt(e*d-1)更快,时间复杂度约为k*sqrt(m)=10^9部分会TLE
预计得分60,但实际只有20分,原因是通过枚举p来验证p-1会存在缺陷,避免漏洞见题解二

#include<bits/stdc++.h>
using namespace std;
long long k, e, d;
long long n; 
int main()
{
	cin>>k;
	while(k--){
		cin>>n>>e>>d;
		int m=e*d-1;
		int sm=sqrt(m);
		bool f=0;//假设无解 
		for(int i=1; i<=sm; i++){
			if(m%i==0 && n/(i+1)==m/i+1){//因为n为long long 类型 
				cout<<i+1<<" "<<m/i+1<<endl;
				f=1;
				break;
			}
		}
		if(!f)cout<<"NO"<<endl;
	}
	return 0;
 } 

题解二:

根据题意可知n=p*q e*d-1=(p-1)*(q-1)
画图通过面积可知:n-e*d+1=p*q-(p-1)*(q-1)=p+q-1n-e*d+2=p+q
问题就转化为n=p*q n-e*d+2=m=p+q
枚举p或者q来验证m的正确性,时间复杂度为k*sqrt(n),预计得分60分

#include<bits/stdc++.h>
using namespace std;
long long k, e, d;
long long n, m;
int main()
{
	freopen("decode4.in", "r", stdin);
	cin>>k;
	while(k--){
		cin>>n>>e>>d;
		m=n-e*d+2;
		int sn=sqrt(n);
		bool f=0;//假设无解
		for(int i=1; i<=sn; i++){//因为p*q=n,枚举p则存在p<=n/p,可得p<=sqrt(n) 
			if(n%i==0 && m-i==n/i){
				cout<<i<<" "<<n/i<<endl;
				f=1;
				break;	
			}
		}
		if(!f)cout<<"NO"<<endl;
	}
	return 0;
}

题解三:

根据题意:n=p*q e*d-1=(p-1)*(q-1)
上述两等式带入后合并可得 q^2-(n-ed+2)*q+n=0问题转换为一元二次方程求解问题,时间复杂度为O(k)

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
LL k, e, d;
LL p, q;//注意如何分析清楚p,q的数据范围
LL q1, q2; //一元二次方程的两个解 
LL n; 
LL b;
LL dt; 
int main()
{
	cin>>k;
	while(k--){
		cin>>n>>e>>d;
		bool f=1;//假设有解 
		b=e*d-n-2;
		dt=b*b-4*n;
		if(dt<0)
			f=0;
		else{
			q1=(-b-sqrt(dt))/2;//解1:(-b-sqrt(dt))/(2*a) ,可能有小数解被精确了 
			q2=(-b+sqrt(dt))/2;//解2:(-b+sqrt(dt))/(2*a) ,可能有小数解被精确了
			if(q1>0 && n%q1==0 && (q1-1)*((n/q1)-1)==e*d-1){//排除负数和小数解 
				q=q1;
				p=n/q1;
			}
			else if(q2>0 && n%q2==0 && (q2-1)*((n/q2)-1)==e*d-1){//排除负数和小数解 
				q=q2;
				p=n/q2;
			}
			else
				f=0;	
		}
		if(f==0)
			cout<<"NO"<<endl;
		else{
			if(p>=q)swap(p, q);//根据题意从小到大输出 
			cout<<p<<" "<<q<<endl;
		}
	}
	return 0;
 } 
posted @ 2022-11-02 15:57  TFLSNOI  阅读(154)  评论(0编辑  收藏  举报