PTA:7-3 冠军魔术
#include<bits/stdc++.h>
using namespace std;
int main(){
int x,n;
cin>>x>>n;
int k=n/2;
int s=n%2;
if(s==1){
cout<<1<<" "<<x*pow(2,k);
}
else{
cout<<0<<" "<<x*pow(2,k);
}
return 0;
}
之前调用pow函数,有一个测试点过不了
后来发现是pow的原因,pow的传参和返回值都是double,double型带来了精度问题,回到上题当x很大时,精度问题就被放大了,所以答案会出错。
#include<bits/stdc++.h>
using namespace std;
int Pow(int a,int b){
int ans=1;
for(int i=1;i<=b;i++){
ans=ans*a;
}
return ans;
}
int main(){
int x,n;
cin>>x>>n;
int k=n/2;
int s=n%2;
if(s==1){
cout<<1<<" "<<x*Pow(2,k);
}
else{
cout<<0<<" "<<x*Pow(2,k);
}
return 0;
}
自己重新写了一个Pow函数,利用简单的一层循环,时间复杂度为O(n),过题了。
但是细看这个问题,发现还是有些不足,pow函数的时间复杂度为O(logN),但自己写的Pow函数时间复杂度为O(N),显然不优。
于是收集了一波别人写的优质代码:
原文链接:https://blog.csdn.net/qq_28114615/article/details/84749629
最容易想到的方法就是通过n此循环x*=x最终来得出答案,不过可想而知,这样是非常低效的,时间复杂度为O(N),那么如何改进这个算法呢?
很简单,我们知道X^n是可以拆分的,
即当n为偶数时,X ^n=X ^(n/2)*X ^(n/2),
当n为奇数时,X ^n=X ^((n-1)/2)*X ^((n-1)/2)*X,
很显然,这个式子不管n是正数还是负数都是成立的。这样就能写出递归部分的代码了:
if(n%2==0)return myPow(x,n/2)*myPow(x,n/2);
else return myPow(x,(n-1)/2)*myPow(x,(n-1)/2)*x;
double myPow(double x, int n) {
if(x==0)return 0;
if(n==1)return x;
if(n==0)return 1;
if(n==-1)return 1.0/x;
if(n%2==0)return myPow(x,n/2)*myPow(x,n/2);
else return myPow(x,(n-1)/2)*myPow(x,(n-1)/2)*x;
return 0;
}
————————————————
版权声明:本文为CSDN博主「HerofH_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28114615/article/details/84749629
很明显,这样的算法复杂度是O(logN)的,不过实际上算法复杂度是O(2logN)的,因为每次递归时都会调用两次相同的递归函数,很明显这样是很不必要的,可以直接将一次调用结果保存即可,对算法进行优化如下:
double myPow(double x, int n) {
if(x==0)return 0;
if(n==1)return x;
if(n==0)return 1;
if(n==-1)return 1.0/x;
if(n%2==0)
{
double temp=myPow(x,n/2);
return temp*temp;
}
else
{
double temp=myPow(x,(n-1)/2);
return temp*temp*x;
}
return 0;
}
————————————————
版权声明:本文为CSDN博主「HerofH_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28114615/article/details/84749629