题意
给定一个长度为 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>=12∗n 时,最大得分即为数组 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;
}