洛谷1010 幂次方 分治算法+掩码的应用
题目链接:https://www.luogu.com.cn/problem/P1010
题目给出一个2e4以内的数,要求把这个数分解成仅含2的幂次方的形式,下图是样例:
由于一个数可以分成多个2的幂次方,可以将其划分为多个子问题,再对每个子问题递归求解,这就是分治算法的精髓。在本题中,分治的最小子问题就是2^0和2^1,对于其他的可以继续递归处理。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 void dfs(int n) 4 { 5 if(n==0)return ; 6 int i=0; 7 while(pow(2,i)<=n)i++;i--;//找出n中包含的最大的二次幂 8 if(i==0)printf("2(0)"); 9 if(i==1)printf("2");//最小的子问题 10 if(i>1) 11 { 12 printf("2("); 13 dfs(i);//分解指数 14 printf(")"); 15 } 16 n-=pow(2,i); 17 if(n)//当n还有剩余不为0的部分时,需要加+ 18 { 19 printf("+"); 20 dfs(n); 21 } 22 } 23 int main() 24 { 25 int n; 26 scanf("%d",&n); 27 dfs(n); 28 }
本题也可以利用位运算来处理,而且也非常高效,代码如下:
1 #include<iostream> 2 using namespace std; 3 void mici(int n) 4 { 5 if(n==0) 6 { 7 cout<<0;//第0位是2(0); 8 return; 9 } 10 if(n==1)return;//第一位只要输出2 11 for( int i=16, mask=0x00008000, first=1;i>=1;i--)//i,mask,first都是局部变量 12 { 13 if(mask&n) 14 { 15 if(!first)cout<<'+';//除第一个外都要写加号 16 cout<<2; 17 if(i!=2)cout<<"("; 18 mici(i-1); 19 20 if(i!=2)cout<<")"; 21 if(first)first=0; 22 } 23 mask>>=1; 24 } 25 } 26 int main() 27 { 28 int x; 29 cin>>x; 30 mici(x); 31 }
每一个不曾起舞的日子,都是对生命的辜负。