2017.12.17
贪心,分治综合习题(1)
1. 2的幂次方表示
思路:本题很容易就想到用递归做。对于2的一次和二次,可以直接打表输出,而且题中所给的数据不大,N<20000,可以预处理把21到215储存在一个数组里,以后好比较。然后就贪心调用函数,把k每次从大到小比较,用s记数,输出括号,进行下一次递归。需要注意的是,在递归中,2的零次幂和2的一次幂是要单独特殊判断的。
核心代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 if(k==0){ 2 printf("0"); 3 return; 4 } 5 else if(k==1) 6 return; 7 while(k){ 8 for(int i=15;i>=0;i--){ 9 if(k>=mi2[i]){ 10 k-=mi2[i]; 11 s++; 12 mo[s]=i; 13 } 14 } 15 } 16 for(int i=1;i<=s;i++){ 17 if(i!=s){ 18 if(mo[i]!=1){ 19 printf("2("); 20 mi(mo[i]); 21 printf(")+"); 22 } 23 else printf("2+"); 24 } 25 else{ 26 if(mo[i]!=1){ 27 printf("2("); 28 mi(mo[i]); 29 printf(")"); 30 } 31 else printf("2"); 32 } 33 }
状态:AC
2. 逆波兰表达式
思路:把整个的前缀表达式分成三个部分:{1.符号 2.这个算式的前半部分 3.这个算式的后半部分}。求出前半部分和后半部分的值,再根据符号做运算。因为前半部分和后半部分不一定只有一个值,可能也是一个算式,所以要使用递归。同时,再在switch中特判一下如果仅仅是一个值的情况。
核心代码:◊
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 char num[500]; 2 scanf("%s",num); 3 switch(num[0]){ 4 case'+': 5 return bolan()+bolan(); 6 case'-': 7 return bolan()-bolan(); 8 case'*': 9 return bolan()*bolan(); 10 case'/': 11 return bolan()/bolan(); 12 default: 13 return atof(num); 14 }
状态:AC
3. 求最大公约数问题
思路:求最大公约数可以使用辗转相除法:假设a > b > 0,那么a和b的最大公约数等于b和a%b的最大公约数,然后把b和a%b作为新一轮的输入。由于这个过程会一直递减,直到a%b等于0的时候,b的值就是所要求的最大公约数。
核心代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 if(a<b){t=a;a=b;b=t;} 2 if(a==b) 3 printf("%d",a); 4 else if(a%b==0) 5 printf("%d",b); 6 7 //以上为需要注意的一些事项(代码) 8 9 int GCD(int i1,int i2){ 10 if(i1%i2==0) 11 return i2; 12 else{ 13 i1=i1%i2; 14 if(i1<i2){ 15 int t; 16 t=i1;i1=i2;i2=t; 17 } 18 return GCD(i1,i2); 19 } 20 }
状态:AC