1-23 周报

1 新学知识: 1.1 快速幂(计算乘方O(log n))   例如5的10次方,怎样算比较快?   (1)5*5…*5, 一步一步算。但是这样太慢了,可以拆分问题。   (2)先算5的5次方,即5*5*5*5*5,再算它的平方,共进行了5次乘法。   (3)先算5*5得25,则5的5次方为25*25*5,再算它的平方,共进行了4次乘法。 递归:   #include <iostream>     using namespace std;     int fun(int a, int b)   {       if (b == 0)           return 1;       else if (b%2 == 1)           return fun(a,b - 1)*a;       else       {           int abs = fun(a,b / 2); //abs存在可以减少递归次数           return abs*abs;       }   }   int main()   {       int a,b;       cin>>a>>b;          cout<<fun(a,b)<<endl;       return 0;   } 非递归(函数):   int fun(int a, int b)   {       int ans = 1;       while(b)    {           if(b%2==1)               ans *= a;           a *= a;           b >>= 1;       //n往右移一位       }       return ans;   } 1.2 整数分解为2的幂相加 递归:   #include <iostream>     using namespace std;     int fun(int n)   {       if (n == 1) return 1;       else if (n%2 == 1)      return fun(n - 1);       else           return fun(n - 1)+fun(n / 2);   }   int main()   {       int a,ans;       while(cin>>a)       {           ans=fun(a);           cout<<ans<<endl;       }       return 0;   } 非递归:   #include <iostream>     using namespace std;     int main()   {       int n;       while(cin>>n)       {           int array[n+1];           for(int i=0;i<=n;i++)               array[i]=1; //初始化为1,表示n拆分为n个1,这一种拆分方法           int k=2;           while(k<=n)           {               for(int j = k;j<=n;j++)//通过将1,合并为2的幂,得到的新的方法。                   array[j]+=array[j-k]; //原有的方法个数,加上新的拆分方法个数               k*=2;           }           cout<<array[n]<<endl;       }    return 0;   } 1.3 计算二进制中1的个数   #include <iostream>     using namespace std;     int main()   {       int k,ans=0;       ans>>k;       while(k)       {               k&=k-1;               ans++;       }       cout<<ans<<endl;       return 0;   }   (1)k-1一个二进制的数减1,就是将这个二进制最右边的那个1变成0,然后它后边的所有位置都变成1~ 举例:0011 0100,减1(n-1)后变成:0011 0011。   (2)k&=(k-1),并操作就会将有0的位置都变成0,上面的例子的结果就是0011 0000,然后再赋值给n,这时n就去掉了一个1,或者叫做计数了一个1。以此类推,就可以得到1的个数。 1.4 更相减损术(求最大公约数)   (1)任意给定两个正整数;判断它们是否均为偶数。若是,则用2约分。   (2)两数相减取绝对值,接着把所得的差与较小的数相减,并取绝对值。继续这个步骤,直到两数相等。则第一步中约掉的若干个2的积与第二步中该数的乘积就是所求的最大公约数。 非递归形式:   #include <iostream>     using namespace std;     int main()   {       int a,b;       cin>>a>>b;       while(a != b)       {           if(a > b)               a-=b;           else               b-=a;       }       cout<<a<<endl;       return 0;   } 递归形式:   #include <iostream>     using namespace std;     int fun(int a,int b)   {       if(a == b)           return a;       else if(a > b)           a-=b;       else           b-=a;       return fun(a,b);   }   int main()   {       int a,b;       cin>>a>>b;       cout<<fun(a,b)<<endl;       return 0;   }   此外,还了解到了一个以前不知道的代码写法:用if(a & 1)代替if(a%2 == 1)。 2 感悟:   我这周做题发现,数学技巧在解决问题中起着很重要的作用,能够简化代码,降低时间复杂度,许多看似困难、复杂的问题,只要运用数学方法,很快就能解决;此外,我操作符和递归方面比较弱,对右移、左移运算符等比较陌生,有待加强。

 

上一篇:SQL入侵教程


下一篇:ExoPlayer记录学习