昨天,第一次参加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…