解密
题目来源
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-1
即n-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;
}