首页 > 其他 > 详细

Educational Codeforces Round 82 (Rated for Div. 2)

时间:2020-03-09 19:56:18      阅读:51      评论:0      收藏:0      [点我收藏+]

QAQ

A. Erasing Zeroes

题意:

给你一个01串,问最少删掉多少个0使得串中的所有1都相邻。

思路:

简单题,详细见代码。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long LL;
int num[maxn];
double E[maxn];
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        string s;
        cin >> s;
        int len  = s.size();
        int i = 0,j = len-1;
        for( i = 0;i<len;++i)
        {
            if(s[i]==1)
                break;
        }
        for( j;j>=0;--j)
            if(s[j]==1)
            break;
            //-=cout <<i << " " <<j << endl;
        int num = 0;
        for(int k = i;k<=j;++k)
        {
            if(s[k]==0)
                ++num;
        }
        cout << num<< endl;
    }
    return 0;
}

B. National Project

题意:

你有n个盒子,你需要往里面去放物品,规则是这样的,必须从左到右开始放物品,你一天可以放一个物品,物品分为ac两种,给你两个数gb,代表你放数的规律是先放g天的物品a,然后在放b天的物品c,循环往复,某个盒子一旦被放置上物品以后就不能够被更改了,但是你可以在选择在某一天不放物品,求最少的天数能使得放置完了以后n个盒子中物品a的数目占到一半以上。

思路:

数学题,具体细节见代码。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long LL;
int num[maxn];
double E[maxn];
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
       LL n,g,b;
       cin >> n >> g >>b;
       LL tmp = (n+1)/2;
       LL ans = 0;
       if(tmp%g!=0)
        ans = tmp/(g)*(g+b)+tmp%(g);
    else
        ans = tmp/g*(g+b)-b;
       ans = max(ans,n);
       cout << ans << endl;
    }
    return 0;
}

C. Perfect Keyboard

题意:

给你一个字符串s,要求你构造出一个a-z的全排列t,使得在s中相邻的两个字符在t中也相邻。可以输Yes和出t,不可以输出No

思路:

考虑能构造的情况实际上就是,对于所有出现的字符,与他相邻的字符种类数不能超过两个,就可以根据s串构造出一个答案链,链的开头以及结尾都是一个只有一个字母相邻,中间则是有两个字母与其相邻,例如s = abcab,此时每个字母都有两个字母与其相邻,无论怎样改变a,b,c的相对位置,都没办法构造出满足条件的t串。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long LL;
bool vis[30];
set<int>st[30];
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        string s;
        cin >> s;
        for(int i = 0;i<=26;++i)
        {
            vis[i] = false;
            st[i].clear();
        }
        int len = s.size();
        if(len ==1)
        {
            printf("YES\n");
            printf("%c",s[0]);
            for(int i = 0;i<26;++i)
            {
                if(!vis[i]&&i!=s[0]-a)
                    printf("%c",i+a);
            }
            printf("\n");
            continue;
        }
        bool flag = true;
        for(int i = 0;i<len;++i)
        {
            vis[s[i]-a] = true;
            if(i!=0)
            {
                st[s[i]-a].insert(s[i-1]-a);
            }
            if(i!=len-1)
            {
                st[s[i]-a].insert(s[i+1]-a);
            }
            if(st[s[i]-a].size()>2)
            {
                //cout << i << endl;
                flag = false;
                break;
            }
        }
        if(!flag)
        {
            printf("NO\n");
            continue;
        }
        int id = -1;
        for(int i =0;i<=25;++i)
        {
            if(st[i].size()==1)
            {
                id = i;
                break;
            }
        }
        if(id==-1)
        {
            printf("NO\n");
            continue;
        }
        int k = 0;
        string ans = "";
        ans+=(id+a);
        ++k;
        id = *st[id].begin();
        set<int>::iterator it;
        //cout << id << " " << ans << endl;
        while(st[id].size()!=1)
        {
            ans+=(id+a);
            ++k;
            for(it = st[id].begin();it!=st[id].end();++it)
            {
                if(*it!=(ans[k-2]-a))
                {

                    id = *it;
                    break;
                }
            }
           // cout << id << " " << ans << endl;
        }
        ans+=(id+a);
        for(int i = 0;i<26;++i)
        {
            if(!vis[i])
                ans+=(i+a);
        }
        printf("YES\n");
        cout << ans << "\n";
    }
    return 0;
}

D. Fill The Bag

题意:

你有一个大小为n的包,你还有m个物品,对于第i个物品它的大小是aiai一定是2k次幂,k是整数,你可以把某个物品分成等大的两个部分,这会增加一次分割次数。问用这m个物品去填满这个背包所需要的最小分割次数是多少,如果不可能填满,则输出-1

思路:

首先,因为物品可以被分隔,只要这些物品的总和大于等于n,那么就一定能填满背包。反之,就输出-1

因为每一个数都是2k次幂,所以考虑根据二进制来解决问题,将每一个数转化为他的二进制形式,我们可以得到两个数组a,ba[i] 表示n的二进制表示中第i位的的值,b[i]表示在m个物品中第i位为1的数有多少个。接下来从低位到高位去遍历,明显,a[i]等于1时代表这一位需要从b中同样在这一位上构造出一个1来,设当前a[i] = 1b数组中小于等于第i位的所有数的和为sum,当sum>=2^i时,为了分割数最小,所以选择用小于等于第i位的所有数来拼凑出第i位为1的情况,反之,则必须要从比第i位高的其他位借位来拼凑出第i1的情况。相对应的更新分割次数以及相关值即可,详细细节可以看代码。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,m;
LL num1[70],num2[70];
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cin >> n >> m;
        for(int i = 0;i<=60;++i)
        {
            num1[i] = num2[i]  =0;
        }
        LL x;
        LL sum = 0;
        for(int i = 0;i<m;++i)
        {
            cin >> x;
            sum+=x;
            for(LL j = 0;j<=60;++j)
            {
                if(x&(1ll<<j))
                {
                    ++num1[j];
                }
            }
        }
        for(LL j =0;j<=60;++j)
        {
            if(n&(1ll<<j))
            {
                num2[j] =1;
            }
        }
        if(sum<n)
        {
            cout << -1 << "\n";
            continue;
        }
        sum=0;
        for(int i = 0;i<=60;++i)
        {
            if(num1[i]&&num2[i])
            {
                num1[i] -=1;
                num2[i] = 0;
            }
        }
        int ans = 0;
        for(LL i = 0;i<=60;++i)
        {
            sum+=((LL)num1[i]*(1ll<<i));
           // cout << sum << " " << ans << " " << i<< "\n";
            if(num2[i])
            {
                if(sum>=(1ll<<i))
                {
                    sum-=(1ll<<i);
                    num2[i] = 0;
                }
                else
                {
                    LL j = i+1;
                    for(j;!num1[j];++j);
                    num1[j]-=1;
                    for(LL k = j-1;k>=i;--k)
                    {
                        ++ans;
                        ++num1[k];
                    }
                    sum+=(1ll<<i);
                }
            }
        }
        cout << ans << "\n";

    }
    return 0;
}

 

Educational Codeforces Round 82 (Rated for Div. 2)

原文:https://www.cnblogs.com/baihualiaoluan/p/12450286.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!