题解
2023-10-15 12:20:37
发布于:广东
224阅读
0回复
0点赞
首先让我们一步步分析问题,题目是让我们求得一个p和一个q,使得p*q=n,e*d=(p-1)(q-1)+1,那么首先我们想到的思路肯定是暴力枚举。从上往下枚举,直到找到第一个符合条件的p和q,代码如下:
#include <bits/stdc++.h>
#define failure_signature -7458732
using namespace std;
pair<long long, long long> chk(long long n, long long e, long long d)
{
for(long long i=1;i*i<=n;i++)
{
if(n%i==0)
{
long long j = n/i;
if(e*d==(i-1)*(j-1)+1) return make_pair(i,j);
}
}
return make_pair(failure_signature, -1);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
long long m,e,d;
cin>>m>>e>>d;
auto res = chk(m,e,d);
if(res.first==failure_signature && res.second == -1) cout<<"NO"<<'\n';
else cout<<res.first<<" "<<res.second<<'\n';
}
}
这段代码的复杂度很明显是 ,那么可以得到多少分呢?经过测试,60分。
在考场上这种代码只适用于追求不高的人。那些追求高的人应该怎么样呢?首先这种有二分性的题目第一眼就应该看出应该是要用二分来解决。并不需要修改太多,只需要把暴力线性枚举改成二分答案就行了。代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int k;
long long n,e,d;
cin>>k;
while(k--){
bool flag=0;
cin>>n>>e>>d;
long long j=e*d;
long long m=n-j+2;
long long l=1,r=m/2;
while(l<r){
long long mid=(l+r+1)/2;
if(mid*(m-mid)>n) r=mid-1;
else l=mid;
}
if(l*(m-l)==n) cout<<min(l,(m-l))<<' '<<max(l,(m-l))<<'\n';
else cout<<"NO\n";
}
return 0;
}
这段代码复杂度是 虽然可以得到100分,但是还有 的算法!这完全就是考验数学,本蒟蒻也不太懂,下面的这个代码参考了 @唱跳坤 的代码,如有侵权,立马删除。
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long k,n,d,e,m;
cin>>k;
while (k--)
{
cin>>n>>e>>d;
m=n-e*d+2;
double p=(m-1.0*sqrt(m*m-4*n))/2.0;
long long llp=p;
long long q=m-p;
if (m*m-4*n<0||llp!=p||llp*q!=n)
cout<<"NO"<<endl;
else
cout<<llp<<" "<<q<<endl;
}
}
至此,以达到最优复杂度,无法继续优化,结束。
全部评论 2
CP003436.[CSP-J 2022] 解密
2023-10-19 来自 吉林
0@梦幻之音 数学法我做讲解了有兴趣可以看一看,知识涉及到的是初中的完全平方公式及逆用
2023-10-19 来自 吉林
0完全平方和还是差?
2024-07-30 来自 广东
0
有帮助,赞一个