一道题两种解法时间复杂度的比较

qq_23908539 2014-12-30 03:34:43
题目是HDOJ的2092

Problem Description
有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假,也就是这种整数到底存不存在,实在有点吃不准,你能快速回答吗?看来只能通过编程。
例如:
x + y = 9,x * y = 15 ? 找不到这样的整数x和y
1+4=5,1*4=4,所以,加起来等于5,乘起来等于4的二个整数为1和4
7+(-8)=-1,7*(-8)=-56,所以,加起来等于-1,乘起来等于-56的二个整数为7和-8



Input
输入数据为成对出现的整数n,m(-10000<n,m<10000),它们分别表示整数的和与积,如果两者都为0,则输入结束。



Output
只需要对于每个n和m,输出“Yes”或者“No”,明确有还是没有这种整数就行了。



Sample Input
9 15
5 4
1 -56
0 0


Sample Output
No
Yes
Yes

这是我自己做的:
#include <stdio.h>
int judge(int a,int b,int m);
int main ()
{
int n,m;
int i,j;
int a,b;
int w;
while(scanf("%d%d",&n,&m)!=EOF&&(m||n))
{
w=0;
if(m>0)
{
if(n%2==0)
{
for(i=0,j=n;i<=n/2;i++,j--)
if(judge(i,j,m))
{
w++;break;
}
if(w==0)printf("No\n");
else printf("Yes\n");
}
else
{
for(i=0,j=n;i<=(n-1)/2;i++,j--)
if(judge(i,j,m))
{
w++;break;
}
if(w==0)printf("No\n");
else printf("Yes\n");
}
}
else
{
if(n%2==0)
{
for(i=0,j=n;i<=n/2;i--,j++)
if(judge(i,j,m))
{
w++;break;
}
if(w==0)printf("No\n");
else printf("Yes\n");
}
else
{
for(i=0,j=n;i<=(n-1)/2;i--,j++)
if(judge(i,j,m))
{
w++;break;
}
if(w==0)printf("No\n");
else printf("Yes\n");
}
}
}
return 0;
}

这是网上的答案:
[code=c]#include <stdio.h>
int main(void)
{
int n, m, i, c;
while(scanf("%d%d", &n, &m) && n || m)
{
c = 0;
for(i = -9999; i < 10000; i ++)
{
if(i*(n-i) == m)
{
c = 1;
}
}
if(c)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}


我觉得两种做法的算法复杂度都是O(n),但我的做法说时间超了,网上的做法AC了,求高手帮忙分析一下,感谢!
...全文
296 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
野男孩 2015-01-01
  • 打赏
  • 举报
回复
引用 2 楼 luciferisnotsatan 的回复:
网上做法可以进一步优化, 比如,x和y的绝对值无论如何都不可能大于积 m的绝对值的。5 4 这个输入只要查 -4 到 4就行了,不用 -9999到9999
恩,还可以进一步优化,5 4这个输入,只需要查-2到2就行了 因为x*y=m, 那么x,y两个中间必有一个的绝对值小于等于sqrt(abs(m));, 当m普遍比较大时,也能省不少计算
lm_whales 2014-12-31
  • 打赏
  • 举报
回复
int n = 0,m = 0; int x = 0,y = 0; int k = 0; int k2= 0; //x+y =n //x-y =k //x= (n+k)/2 for(cin>>n>>m; n!=0 && m!=0 ;cin>>n>>m) { k2 =n*n -4*m; //cout <<"n="<<n<<",m=" <<m<<",k2="<<k2<<"k="<<k<<endl; if(k2<0){ cout<< "No "<<endl; } else { k =sqrt(k2);// 用移位算法,大约16 次移位 // cout <<"n="<<n<<",m=" <<m<<",k2="<<k2<<"k="<<k<<endl; if(k*k !=k2) { cout <<"No"<<endl; } else { x = n + k; y = n - k; if((x&1 )==1 )cout<<"No"<<endl; else cout<<"Yes"<<endl;//<<" x="<<x/2 <<",y = "<<y/2<<endl; } } } 这个算法理论上,应该是 O(1)的
lm_whales 2014-12-31
  • 打赏
  • 举报
回复
x -y = sqrt( (x+y)*(x+y) -4* x*y) x = ((x+y) +(x-y))/2 y = (x+y -(x-y))/2; 这一步,用奇偶性判断 x,y 是否整数 1) (x+y)*(x+y) -4* x*y >0 2) (x+y)*(x+y) -4* x*y 是个 完全平方数 这一步,可以采用移位开平方方法计算,有余数为假 也可以简单点,用浮点数开方 如果 (x-y) *(x-y ) = (x+y)*(x+y) -4* x*y 是个 完全平方数
lm_whales 2014-12-31
  • 打赏
  • 举报
回复
这个解一元二次方程,看有没有整数解即可
赵4老师 2014-12-30
  • 打赏
  • 举报
回复
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
shenchenman 2014-12-30
  • 打赏
  • 举报
回复
judge是什么? judge的额外算法维度决定了你的算法相对于第二种算法的额外维度
luciferisnotsatan 2014-12-30
  • 打赏
  • 举报
回复
网上做法可以进一步优化, 比如,x和y的绝对值无论如何都不可能大于积 m的绝对值的。5 4 这个输入只要查 -4 到 4就行了,不用 -9999到9999
luciferisnotsatan 2014-12-30
  • 打赏
  • 举报
回复
网上的做法比lz少了很多if else判断,大量计算,还有judge的调用。就算都是O(n),对方每一次的时间花销都比你的代码小多了。 而且,网上直接用公式做,简单明了。 x+y = n =》 y = n - x 然后x×y = m =》 x × (n - x) = m 就是 if(i*(n-i) == m) 这个判断 lz的没仔细看,不知道是怎么算的。

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧