c/c++倍增法的原理,代码演示及运用

1.倍增法的原理

        倍增法顾名思义就是“成倍增长”。那么倍增法只是乘2就了事了吗?对于后缀数组等,有时确实可以简单地乘2。但,大多数题目都可以有更好的解法,那就是利用二进制本身的倍增特性将其展开。如27,27=2^4+2^3+2+1。

        任何一个整形n的二进制都只有log2 n位。那么就可以从0快速增长到n,只需要log2 n步。

2.倍增法的例题

【题目描述】任何一个正整数,都可以用2的幂次方来表示,例如:137 = 2^7+2^3+1
 在这里,我们约定次方用括号来表示,即a^b
可以表示成a(b)。由上述可知,137又可以表示为:2(7) + 2(3) + 2(0)。进一步可表示为:7 =2^2+2+1= 2(2) + 2 + 2(0)     而    3 = 2 +1= 2 + 2(0)。

所以最后137可以表示为:2(2(2) + 2 + 2(0)) + 2(2 + 2(0)) + 2(0)。又比如:1315  最后可以表示为:2(2(2 + 2(0) +2)) + 2(2(2 + 2(0))) + 2(2(2) + 2(0)) + 2 + 2(0)
【输入】两个正整数m(m ≤ 20000)接下来m行每行输入一个n  (n ≤ 100000)
【输出】m行,每行输出相应的n展开后的结果
【样例输入】

2

137

1315
【样例输出】2(2(2) + 2 + 2(0)) + 2(2 + 2(0)) + 2(0)

2(2(2 + 2(0) +2)) + 2(2(2 + 2(0))) + 2(2(2) + 2(0)) + 2 + 2(0)

问题分析:

任何一个满足n=a0*2^0+a1*2^1+a2*2^2+···

其中a0,a1,a2···表示n的二进制的1或0。

如36=2^5+2^2,那么我们只需要知道5和2展开的结果,再将其包在2()中即可

所以递推公式为:如果n是质数则w[n]=2(w[(int)(log2(n))])

否则w[n]=2(w[(int)(log2(n))])+w[i-pow(2,(int)(log2(i)))]

以下是代码的实现

#include<iostream>
#include<cmath>
using namespace std;
#define N 100010
struct node{
	string s;
}w[N];
int LOG[N];
void put(int n){
	for(int i=0;i<=n;i++){     //也可以提前计算出LOG[N]的值
		LOG[i]=LOG[i>>2]+1;
	}
}
void init(int n){
	for(int i=4;i<=n;i++){
		if(!(i&(i-1))){           //i是质数时,做相应处理
			w[i].s="2(";
			w[i].s+=w[(int)(log2(i))].s;
			//等效于w[i].s+=w[LOG[i]].s;
			w[i].s+=")";
		}else{
			//否则加上w[i-pow(2,(int)(log2(i)))].s
			//等效于w[i-pow(2,LOG[i])].s
			int k=pow(2,(int)(log2(i)));
			w[i].s="2(";
			w[i].s+=w[(int)(log2(i))].s;
			w[i].s+=")+";
			w[i].s+=w[i-k].s;
		}
	}
}
int main(){
	int m;
	cin>>m;
	w[1].s="2(0)";
	w[2].s="2";
	w[3].s="2+2(0)";
	int *a=new int[m];
	int maxsize=0;
	for(int i=0;i<m;i++){
		cin>>a[i];
		maxsize=max(maxsize,a[i]);
	}
	init(maxsize);
	for(int i=0;i<m;i++){
		cout<<w[a[i]].s;
		if(i+1!=m)cout<<endl;
	}
	return 0;
}

家人们,本宝宝求三连。如有错误请联系本宝宝修改。如有侵权请联系本宝宝删除,谢谢各位的观看。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值