CSP2022-T2(解密)
【题目来源】:http://oj.tfls.net/d/lnzt/p/14

【分析】由题目可知:n=p×q,e×d=(p−1)(q−1)+1,化解可得:e×d=p×q-p-q+1+1=n-p-q+2,又从题目可知:m=n-e×d+2,合并可得,m=p+q。
【20分】枚举,时间复杂度O(n*k) (实测40分)
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main() {
5 int k,m,i,n,d,e,p,q;
6 cin>>k;
7 while(k--){
8 cin>>n>>d>>e;
9 m=n-e*d+2;
10 for(i=1;i<=n;i++){
11 p=i; //枚举p值
12 if(n%p==0){
13 q=n/p; //满足n=p*q
14 if(p+q==m){ //满足m=p+q
15 cout<<p<<" "<<q<<endl;
16 break;
17 }
18 }
19 }
20 if(i>sqrt(n)) cout<<"NO"<<endl;
21 }
22 return 0;
23 }
【60分】枚举p时,不需要从1到n,只需要到sqrt(n)。时间复杂度O(sqrt(n)*k)
//设n=36,则有
//1*36=36
//2*18=36
//3*12=36
//4*9=36
//6*6=36 p=sqrt(n)
//9*4=36 此时p,q出现重复
1 for(i=1;i<=sqrt(n);i++)
【100分】数学问题。
方法一:一元二次方程。分析可得:n=p×q,m=p+q,那么很容易想到(我当然知道这句话很欠揍)一元二次方程中根与系数的关系x1+x2=-b/a,x1*x2=c/a,可以构建一元二次方程x2-(x1+x2)x+x1*x2=0,即x2-mx+n=0,p、q为方程的两个根。题目中要求p、q为正整数,可以在求出根后利用n=p×q,m=p+q反向验证p、q是否符合题意。
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main() {
5 long long k,m,n,d,e,p,q,det,s;
6 cin>>k;
7 while(k--) {
8 scanf("%lld%lld%lld",&n,&d,&e);
9 //cin>>n>>d>>e;
10 m=n-d*e+2;
11 det=m*m-4*n; //计算根的判别式△ ,注意此处需计算m*m,会超出int范围
12 if(det<0) { //△<0,方程没有实数根
13 cout<<"NO"<<endl;
14 continue;
15 }
16 p=(m-sqrt(det))/2; //计算p、q,且需按题意p<=q
17 q=(m+sqrt(det))/2;
18 if(p>0&&q>0&&p*q==n&&p+q==m) //反向验证p、q是否满足题意
19 //cout<<p<<" "<<q<<endl;
20 printf("%lld %lld\n",p,q);
21 else //cout<<"NO"<<endl;
22 printf("NO\n");
23 }
24 return 0;
25 }
方法二:二元一次方程组。分析可得:n=p×q,m=p+q,利用完全平方公式(p+q)2=p2+2pq+q2,(p-q)2=p2-2pq+q2,可以推出(p-q)2=(p+q)2-4pq=m2-4n,可得二元一次方程组:p-q=sqrt(m2-4n) ①,p+q=m ②,①+②得:2p=sqrt(m2-4n)+m,解得:p=(sqrt(m2-4n)+m)/2,q=n/p。
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main() {
5 long long k,m,n,d,e,p,q,det,s;
6 cin>>k;
7 while(k--) {
8 scanf("%lld%lld%lld",&n,&d,&e);
9 //cin>>n>>d>>e;
10 m=n-d*e+2;
11 p=(sqrt(m*m-4*n)+m)/2;
12 q=n/p;
13 if(p>q) swap(p,q);
14 if(p>0&&q>0&&p*q==n&&p+q==m) //反向验证p、q是否满足题意
15 printf("%lld %lld\n",p,q);
16 else //cout<<"NO"<<endl;
17 printf("NO\n");
18 }
19 return 0;
20 }

浙公网安备 33010602011771号