之前在学多重背包(涉及三重循环)时曾经大佬教过二进制拆分,今天看到快速幂用了两个方法:分治,二进制拆分。突然就联想到了多重背包,但是想到二进制拆分时又忘记咋做了,特此总结复习。
首先看看多重背包的二进制拆分。
我们知道多重背包的每种物品有p[i]个,二进制拆分就是要这些个物品按照二进制的方式拆分,然后转化为0-1背包问题求解,不难想到其实应该有一个1 2 4 8…的系数在进行作用。这个系数具体来讲可以说是一个满足 p[i]-pow(2,k)+1>0最大k值形成系数:1,2,4,…,pow(2,k-1)。最后我们还要加上一个防止系数越界的数。
例如p[i]如果为13那么系数就是 1 2 4 6
具体代码如此:
void DP()
{
for(int i=1;i<=n;i++)
{
int num=min(p[i],p[i]/V)//你背包能装多少,如果只能装8个我p[i]也没必要拆分100个啊
for(int k=1;num>0;k<<=1)
{
if(k>num)//边界维护
{
k=num;
}
num-=k;//边界维护
for(int j=V;j>=cost[i]*k;j--)
{
dp[j]=max(dp[j],dp[j-cost[i]*k]+value[i]*k);
}
}
}
}
我们再来看看快速幂的二进制拆分
void fastpow(int n,int a)//a的n次幂
{
int ans=1;
while(n)
{
if(n&1)//相当于判断奇数
ans*=a;//1位有数当乘
a*=a;//系数进阶
n>>=1;
}
return ans;
}
快速幂的另一种方法是采用了分治的方法(说到这里想起了归并排序)
void fastpow(int n,int a)
{
if(n==1)
return a;
int fpow=fastpow(n/2,a);//细分
if(n&1)//开始归并
return fpow*fpow*a
return fpow*fpow;
}
这个归并也要好好琢磨