Educational Codeforces Round 122 (Rated for Div. 2) 简训

导语

涉及的知识点

思维,DP

链接:Educational Codeforces Round 122 (Rated for Div. 2)

题目

A Div. 7

题目大意:给出一个正整数n,每次操作可以改变一位上的数,现在要求操作的结果没有前导0并且可以被7整除,求出操作最少次数后得到的结果数

思路:虽然可以操作每一位,但其实只用操作最后一位即可,因为最后一位尝试所有数后必然有一个使得整个数是7的个数

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int maxn=2e5+5;
int t,n,num[4],cnt;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n;
        cnt=3;
        if(n%7==0)//特判初始就符合条件的
        {
            cout <<n<<endl;
            continue;
        }
        while(n) {//按位拆分
            num[cnt--]=n%10;
            n/=10;
        }
        bool flag=0;
        cnt++;
        if(cnt==3) {//如果只有一位
            cout <<"7\n";
            continue;
        }
        for(int j=0; j<=9; j++) {//只需要尝试变动最后一位即可
            int tmp=num[3],res=0;
            num[3]=j;
            for(int k=cnt;k<=3;k++)
            {
                int p=3-k,in=num[k];
                while(p--)in*=10;
                res+=in;
            }
            if(res%7==0) {
                flag=1;
                cout <<res<<endl;
                break;
            }
            num[3]=tmp;
            if(flag)break;
        }
    }
    return 0;
}

B Minority

题目大意:给出一个01串,现在需要选择一个严格连续子串,对于这个子串,如果里面0多则去掉子串所有1,否则相反,这样的去掉一次0/1定义一次操作,现在求出只能进行一次操作的情况下能够去掉的最多个数是多少

思路:统计01个数,如果不等,直接输出小值即可(可以模拟一下,去掉首或者尾或者都不拿),如果相等,输出相等值-1即可

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
int t;
string s;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>s;
        int len=s.length(),z=0,o=0;
        for(int i=0;i<len;i++)//统计个数
            if(s[i]=='0')z++;
            else o++;
        cout <<(o==z?o-1:min(o,z))<<endl;//特判
    }
    return 0;
}

C Kill the Monster

题目大意:略

思路:直接判断互相需要几次才能消灭对方即可,同归于尽也算可行解

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,hc,dc,hm,dm,k,w,a;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>hc>>dc>>hm>>dm>>k>>w>>a;
        if((hc+dm-1)/dm>=(hm+dc-1)/dc) {//判断初始是否合法
            cout <<"YES\n";
            continue;
        }
        bool flag=0;
        for(int i=0; i<=k; i++) {
            int hcc=hc,ddc=dc;
            hcc+=(k-i)*a,ddc+=i*w;
            if((hcc+dm-1)/dm<(hm+ddc-1)/ddc)//需要向上取整
                continue;
            else {
                flag=1;
                cout <<"YES\n";
                break;
            }
        }
        if(flag)continue;
        cout <<"NO\n";
    }
    return 0;
}
/*
1 1
1 2
0 0 0
*/

D Make Them Equal

题目大意:给出一个长度为 n n n的序列 a a a,初始时序列每个值为1,现在进行下列操作:选择两个整数 i ( 1 ≤ i ≤ n ) , x ( x > 0 ) i(1\le i\le n),x(x>0) i(1in),x(x>0) a i = a i + ⌊ a i x ⌋ a_i=a_i+⌊\frac{a_i}{x}⌋ ai=ai+xai,进行完所有的操作之后,如果 a i = b i a_i=b_i ai=bi,将获得 c i c_i ci的价值,现在能最多进行k次操作,询问能获得最大价值

思路:首先数据量给的有点大,看似吓人,其实用不到那么多次操作,对于 a i a_i ai来说,从1到1e3最少只需要12次操作,将 a i a_i ai到对应 b i b_i bi的次数作为花费,价值为 c i c_i ci,那么原题就转变为,背包容量为k,每件物品花费为转移次数,价值为 c i c_i ci的01背包问题,总操作次数是不会超过 1.2 × 1 0 4 1.2×10^4 1.2×104的,所以直接背包容量开这么大即可(而不是 1 0 6 10^6 106

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e3+5;
int t,n,k,b[maxn],c[maxn],a[maxn],dp[maxn*10+2121];
int v[maxn]= {0,0,1,2,2,3,3,4,3,4,4,5,4,5,5,5,4,5,5,
              5,5,5,6,6,5,6,6,6,6,7,6,6,5,6,6,6,6,6,6,7,6,7,6,7,7,7,7,7,
              6,7,7,7,7,7,7,7,7,7,8,8,7,8,7,7,6,7,7,7,7,7,7,7,7,7,7,8,7,8,8,
              8,7,8,8,8,7,7,8,8,8,8,8,8,8,8,8,8,7,8,8,8,8,8,8,8,8,8,8,9,8,8,
              8,8,8,8,8,8,9,9,9,9,8,9,9,9,8,9,8,8,7,8,8,8,8,8,8,8,8,8,8,8,8,9,8
              ,9,8,9,8,9,8,8,9,9,8,8,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
              8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,9,10,9,9,9,10,9,9,9,10,9,10,9,9,9,10,10,10,
              10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,9,10,9,9,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
              9,9,9,9,9,9,9,9,9,9,9,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,9,10,10,10,10,10,9,10,9,
              9,10,10,10,10,10,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,10,
              10,10,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
              10,11,10,10,10,10,10,10,10,11,10,10,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
              10,10,10,10,10,11,10,10,10,10,10,10,10,10,10,10,10,11,10,10,10,11,10,10,10,11,11,11,11,11,10,11,11,
              11,10,11,10,11,10,11,11,11,10,11,10,10,10,11,11,11,10,10,10,11,10,11,10,10,10,11,11,11,11,11,11,11,11,
              11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,
              11,10,11,11,11,10,11,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
              10,10,11,10,11,10,11,10,11,10,11,10,11,10,10,10,11,10,11,10,11,10,11,10,11,10,10,11,11,11,11,10,11,11,
              11,11,11,11,11,10,11,11,11,11,11,11,11,10,10,11,11,11,11,11,11,10,11,11,11,10,10,11,11,11,11,11,11,11,11
              ,11,11,10,11,11,11,10,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
              10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,
              11,11,11,11,10,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
              11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,12,12,11,11,11,12,11,
              11,11,12,11,12,11,11,11,11,12,12,11,12,11,12,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
              11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,12,11,12,11,11,12,12,11,12,11,11,11,12,
              11,12,11,11,11,11,11,12,11,11,11,12,11,12,11,11,12,12,11,12,11,11,11,12,12,12,11,12,11,12,11,11,12,12,12,12,
              12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,11,11,12,12,11,12,12,12,12,12,12,12,11,12,12,12,11,12,
              11,11,11,12,12,12,12,12,12,12,11,12,11,12,11,11,12,12,11,12,12,12,11,12,11,12,11,11,12,12,12,12,12,12,12,12,12,12,
              12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,
              12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,
             };//预处理的值
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n>>k;
        int ans=0;
        for(int i=1; i<=n; i++) {
            cin >>b[i];
            b[i]=v[b[i]];//直接替换成费用
            ans+=b[i];
        }
        for(int i=1;i<=n;i++)cin >>c[i];
        for(int i=0; i<=min(ans,k); i++)dp[i]=0;//初始化
        for(int i=1; i<=n; i++)//空间压缩后的背包DP
            for(int j=min(k,ans); j>=b[i]; j--)
                dp[j]=max(dp[j],dp[j-b[i]]+c[i]);
        cout <<dp[min(k,ans)]<<endl;
    }
    return 0;
}

参考文献

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值