Make Them Equal(cf1633D)【变形01背包】

传送门

题意

给定一个长度为 n n n 且元素全为 1 1 1 的数组 a a a ,并可对该数组进行最多 k k k 次操作,每次操作可以任取一个 i i i 及一个整数 x x x ,并执行以下公式: a i = a i + ⌊ a i / x ⌋ a_i=a_i+⌊a_i/x⌋ ai=ai+ai/x ,在所有的操作之后,同时将给定数组 b b b c c c ,若 a i = b i a_i=b_i ai=bi ,则可获得 c i c_i ci 的得分,求最后能够获得的最大得分。

分析

首先通过打表得出令 a i = b i a_i=b_i ai=bi 所需次数的规律,可以发现达成任意数字需要的最大操作次数不超过 12 12 12 ,因此当 k > = 12 ∗ n k>=12*n k>=12n 时,最大得分即为数组 c c c 之和。同时,使得 a i = b i a_i=b_i ai=bi 所需要的次数也可将原先的 b b b 数组进行替换,由此该问题可看作每件物品的体积为 b i b_i bi ,价值为 c i c_i ci ,总体积为 k k k 的背包。代入 01 01 01 背包板子即可。注意一定要进行初始化。

参考代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,k,d[2010],b[2010],c[2010];
int f[12010];

void solve(){
	for(int i=1;i<1000;i++)
		for(int j=1;j<=i;j++)
			d[i+i/j]=min(d[i+i/j],d[i]+1);
}

signed main(){
	cin>>T;
	memset(d,0x3f,sizeof(d)); 
	d[1]=0;
	solve();
	while(T--){
		int x,sum=0;
		cin>>n>>k;
		for(int i=1;i<=n;i++){
			cin>>x;
			b[i]=d[x];
		}
		for(int i=1;i<=n;i++){
			cin>>c[i];
			sum+=c[i];
		}
		if(k>=12000){
			cout<<sum<<endl;
			continue;
		}
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++){
			for(int j=k;j>=b[i];j--)
				f[j]=max(f[j],f[j-b[i]]+c[i]);
		}
		cout<<f[k]<<endl;
	}
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值