D.Make Them Equal-Educational Codeforces Round 122 (Rated for Div. 2)

题目描述

You have an array of integers aa of size nn . Initially, all elements of the array are equal to 11 . You can perform the following operation: choose two integers ii ( 1 \le i \le n1≤i≤n ) and xx ( x > 0x>0 ), and then increase the value of a_iai​ by \left\lfloor\frac{a_i}{x}\right\rfloor⌊xai​​⌋ (i.e. make a_i = a_i + \left\lfloor\frac{a_i}{x}\right\rfloorai​=ai​+⌊xai​​⌋ ).

After performing all operations, you will receive c_ici​ coins for all such ii that a_i = b_iai​=bi​ .

Your task is to determine the maximum number of coins that you can receive by performing no more than kk operations.

输入格式

The first line contains a single integer tt ( 1 \le t \le 1001≤t≤100 ) — the number of test cases.

The first line of each test case contains two integers nn and kk ( 1 \le n \le 10^3; 0 \le k \le 10^61≤n≤103;0≤k≤106 ) — the size of the array and the maximum number of operations, respectively.

The second line contains nn integers b_1, b_2, \dots, b_nb1​,b2​,…,bn​ ( 1 \le b_i \le 10^31≤bi​≤103 ).

The third line contains nn integers c_1, c_2, \dots, c_nc1​,c2​,…,cn​ ( 1 \le c_i \le 10^61≤ci​≤106 ).

The sum of nn over all test cases does not exceed 10^3103 .

输出格式

For each test case, print one integer — the maximum number of coins that you can get by performing no more than kk operations.

----------------------------------------------------------------------------------------------首先,a[i]初始时1,每次操作,x取1时可以翻倍,所以要得到1000(b[i]最大范围)总次数还是很少的,远低于k(1<=k<=1e6)一定的k,每次操作消耗一定k,获得一定价值,自然联想到背包,得到b[i]的次数需要预处理,比较省时,且比较容易进行背包。

预处理,对于每一个b[i],可以凭借小于等于它的j,推出大于它的b[i],注意j要小于等于i,j大于i时就一直停留在b[i]上止步不前。这样,每次循环,i都能推出至少比它大1的,而本次循环之后的循环又只能推出比本次更大的(不会影响到本次),所以这样推没毛病

        for(int i=1; i<=1000; i++)
        {
            for(int j=1; j<=i; j++)
            f[i+i/j]=min(f[i+i/j],f[i]+1);

        }

---------------------------------------------------------------------------------------------------------------------------------

一维背包,参考背包九讲,f[b[i]]就是本次花费,w[i]是得到的奖励

memset(dp,0,sizeof(dp));
            for(int i=1; i<=n; i++)
            {
                for(int j=k; j>=f[b[i]]; j--)
                {
                    dp[j]=max(dp[j],dp[j-f[b[i]]]+w[i]);
                }
            }

            cout<<dp[k]<<'\n';

------------------------------------------------------------------------------------------------------------------------

由于k非常大,可以在预处理的时候求一下f[i]的最大值,当n*f[i]最坏情况都《=k时,直接输出总和就行

代码如下

#include<cstdio>
#include<stack>
#include<iostream>
# include<algorithm>
# include<map>;
# include<cstring>
using namespace std;
typedef long long int ll;

int f[101000];
int b[1010];
int w[1010];
ll dp[1010000];
int main()
{

    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&b[i]);

        }
        ll sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&w[i]);
            sum+=w[i];
        }

        fill(f,f+1001,999999);
        f[1]=0;
        int mx=-1;
        for(int i=1; i<=1000; i++)
        {
            for(int j=1; j<=i; j++)
                f[i+i/j]=min(f[i+i/j],f[i]+1);

        }
        if(k>=mx*n)
        {
            cout<<sum<<'\n';
        }
        else
        {
            memset(dp,0,sizeof(dp));
            for(int i=1; i<=n; i++)
            {
                for(int j=k; j>=f[b[i]]; j--)
                {
                    dp[j]=max(dp[j],dp[j-f[b[i]]]+w[i]);
                }
            }
            cout<<dp[k]<<'\n';
        }

    }

    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值