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 }
posted @ 2022-11-27 11:29  TFLSZXL  阅读(211)  评论(0)    收藏  举报