学习快速幂,送你一道ACM题

昨天,第一次参加ACM竞赛,从写完第一题的提交,整个人就处于自闭状态。
原因是吧,要是题目不会写,那是咱能力的问题,也就没啥好说的,关键是,写出来的题目,提交它就死活过不去。那种感觉你懂的在这里插入图片描述
其中就有一道这样的题目,给你们看一眼,咱也不知道题目为啥叫“禁止套娃”,感觉明明就像是套娃╮(╯▽╰)╭

在这里插入图片描述
给了一个输入输出样例:
输入样例:2
输出样例:9

不知道你们第一眼看懂了题目没有,反正我是没有,也不跟你们分享我当时错误的想法了,免得误导你们。
集合中有两个元素

原集合的子集 对应元素个数的子集个数 子集的子集个数
2个元素一个不取(空集,1个) 1 2^0
2个元素任取一个(两个) 2 2^1
2个元素全部取到(一个) 1 2^2

简单的把问题分析过后,最后的结果是9,就是上面表格最后两列,每一行两数相乘之后再相加。其中对应元素个数的子集个数,就是我们数学上的排列组合问题。(C2_0,C2_1,C2_2,原谅我不会正确打出这个字符ˉ▽ˉ…)

原以为我找到了问题的精髓,但是这道题没有AC,原因是没有通过所有的测试案例,我提交了三四次,然后就放弃了。竞赛结束后,看到这道题的题解:在这里插入图片描述
分析过程没错,题解也没错。嗯,记住就行了,简单粗暴。

接下来,要分析的是快速幂

以前在一些课程中知道这种用法,昨天是第一次知道它还有名字,叫做快速幂。快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。直接看代码,

常规求幂:

int pow1(int a,int b)   //a^b
{
    
   int r=1;
   while(b--) r*=a;
   return r;
} 

快速求幂(递归):

int pow2(int a,int b)    //a^b
{
       
    if(b==1) return a;
    int temp=pow2(a,b/2);
    return (b%2==0 ? 1 : a)*temp*temp;
}

相比于快速求幂一般的代码来说,我觉得递归的代码比较好理解,所以我把它放在了前面。当然,快速求幂一般的代码也不是特别难。

快速求幂(一般):

int pow3(int a,int b)	//a^b
{
    
    int r=1,base=a;
    while(b!=0)
    {
    
    if(b%2) 
    	r*=base;
    base*=base; //不管是否执行if内的语句,该句都会执行
    b/=2;
    }
    return r;
}

快速求幂(位运算):

int pow4(int a,int b){
    
  if(b==0) return 1;
  else {
    
    while((b&1)==0)//b&1,取b二进制的最低位,判断和1是否相同,相同返回1,否则返回0,可用于判断奇偶
    {
    
      b>>=1;//把b的二进制右移一位,即去掉其二进制位的最低位
      a*=a;
    }
  }
  int result=a;
  b>>=1;
  while(b!=0){
    
    a*=a;
    if(b&1) 
    	result*=a;
    b>>=1;
  }
  return result;
}

那道题的代码不重要,
重要的是学会快速幂,
更重要的是知道快速幂的存在,知道快速幂的代码,知道那道题的题解是3^n…

猜你喜欢

转载自blog.csdn.net/xiaobai_qian/article/details/106060093