Educational Codeforces Round 82 (Rated for Div. 2)(A~D)

A. Erasing Zeroes(水题)

分析

  • 题意
  1. 给我一个长度为n的01字符串,问我最少删去多少个0,是字符串中所有的1连续?
  • 思路
  1. 直接找字符串中第一个1,和最后一个1直接的0的数量

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt", "w", stdout); }
using namespace std;

const int mxn = 2e5 + 10;

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        string s;
        cin >> s;
        int l = 0, r = 0;
        for(int i = 0; i < s.size(); i ++)
        {
            if(s[i] == '1')
            {
                l = i + 1;
                break;
            }
        }
        for(int i = s.size() - 1; i >= 0; i --)
        {
            if(s[i] == '1')
            {
                r = i - 1;
                break;
            }
        }

        int fg = 0;
        for(int i = l; i <= r; i ++)
        {
            if(s[i] == '0')
                fg ++;
        }
        if(r == 0)
        {
            printf("0\n");
            continue;
        }
        printf("%d\n", fg);
    }


    return 0;
}

B. National Project

分析

  • 题意
  1. 一个施工队要修一个长度为n的路,每天可以修路的长度为1,由于气候原因在,每过g天好的天气,就会有b天坏天气,在好的天气修路可以使那一段路的质量是好的,否则路的质量就不好
  2. 在施工队要保证这个这条的至少一半以上 的距离都是 好质量路,问最少需要修多少天的路?(注意:施工队在某天可以选择修或不修路)
  • 思路
  1. 本质就是考察队周期行应用的细节,由于我的代码写的太乱,所以就拿了一个大佬的代码,来讲思路,我设要修的高质量路的长度为 q
  2. 我们考虑如果q%g==0,能在q/g个周期内完成,这时候我们考虑第q/g个周期,这个是周期由两部分组成第一个部分是g天的好天气,我们利用这个g天的好天气,就恰好完成了修长度为q的长度的高质量路的任务,而第二部分的b天的坏天气实际上是不需要的,,所以这个时候至少要耗费的时间是 t = ( q / g 1 ) ( g + b ) + g t = (q/g-1)*(g+b)+g ,接下来我们要担心的是那么剩下的不需要保证质量的路程n-q的距离都修完了吗?这个时候就体现了输出的时候max的作用,如果t>=n说明把好的路修完之后,q/g个周期中第二部分的坏天气已经,把剩下的路都修好;如果t<n的话是不要求质量的路还没有被 q/g * b的坏天气修完,这个时候要耗费的天数是n,
  3. 考虑q%g!=0,这种情况本质与第第一种情况相同,只不过由于q%g!=0,所以周期要 q/g+1,最后也是特殊考虑最后一个周期

代码1(大佬的)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define me(a,x) memset(a,x,sizeof a)
#define pb(a) push_back(a)
#define pa pair<int,int>
#define fi first
#define se second
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
 
        ll n,g,b;
        cin>>n>>g>>b;
        ll q=n/2+n%2;
        ll ans;
        if(q%g==0)
        {
            ans=q/g;
            ans=ans*g+(ans-1)*b;
        }
        else
            ans=q/g+1,ans=(ans-1)*(g+b)+q%g;
            cout<<max(n,ans)<<endl;
 
    }
 
    return 0;
}

代码2(巨弱的)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt", "w", stdout); }
using namespace std;
#define ll long long 

const int mxn = 2e5 + 10;

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        ll n, a, b;
        scanf("%lld %lld %lld", &n, &a, &b);
        ll lenp = n / 2;
        if(n%2) lenp ++;
        ll T = lenp / a;
        ll lenf = n/2;
        if(lenp % a == 0)
        {
            lenp = lenp % a;
            lenf = max(0LL, lenf - (T - 1) * b);
            printf("%lld\n", T * a + (T - 1) * b + lenf + lenp);
        }

        else
        {
            lenp = lenp % a;
            lenf = max(0LL, lenf - T * b);
            printf("%lld\n", T * a + T * b + lenf + lenp);
        }

    }


    return 0;
}

C. Perfect Keyboard(模拟)

分析

  • 思路
    直接模拟就可以了,,

代码

#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
#define ios ios::sync_with_stdio(false)
#define fre                          \
{                                    \
    freopen("A.txt", "r", stdin);   \
    freopen("Ans.txt", "w", stdout); \
}
const int mxn = 1e2 + 50;

char ar[mxn];
int pos[mxn];


int main()
{
    ios;
    /* fre; */
    string  s;
    int T;
    cin >> T;
    while(T --)
    {
        cin >> s;
        int n = s.size();
        memset(ar, '@', sizeof(ar));
        memset(pos, 0, sizeof(pos));
        int p = 30, fg = 1;
        for(int i = 0; i < n; i ++)
        {
            if(! pos[s[i]])
            {
                if(ar[p + 1] == '@')
                    ar[++ p] = s[i];
                else if(ar[p - 1] == '@')
                    ar[-- p] = s[i];
                else
                {
                    fg = 0;
                    break;
                }

                pos[s[i]] = p;
            }
            else
            {
                if(abs(pos[s[i]] - p) == 1)
                {
                    p = pos[s[i]];
                }
                else
                {
                    fg = 0;
                    break;
                }
            }
        }

        if(fg)
        {
            printf("YES\n");
            for(int i = 0; i < mxn; i ++)
                if(ar[i] !='@')
                    printf("%c", ar[i]);
            for(int i = 0; i < 26; i ++)
            {
                if(pos['a' + i] == 0)
                {
                    printf("%c", 'a' + i);
                }
            }
        }
        else
            printf("NO");
        printf("\n");
    }

    return 0;
}


D. Fill The Bag

分析

  • 题意
  1. 给我们n个由2次方形成的数的序列ar,每次操作我们都可以选择ar中的一个数a,把a变成2个a/2,问我们能否过这样的一些操作把ar中的数字拼凑出数字和为m,如果能最少的操作次数是多少次?
  • 思路
  1. 这题明显考察二进制应用问题,首先我们对所给的n个数中的每个数 a r [ i ] = = 2 k ar[i]==2^k ,我们 n u m [ k ] + + num[k]++ 统计将n个数二进制拆分之后的数量,
  2. 之后我们在对要拼凑出的m的二进制为下的每一位从低位到高位进行考虑,如果m的二进制下的第i位是1,那么我们考虑,这个第i位的1所代表的十进制数设为x,我们怎么得到? 有三种情况:
    • 第一种:如果num[i] >=1 ,ok直接有数与x相同,那么直接拿来用就行
    • 第二种:如果从更低的二进制为,进位而来(就是一些更下的数相加组合之后的和为x)-----这也是什么我们从m的低二进制位往高位开始考虑,就是考虑到 第二种情况 才这样的
    • 第三种:如果我人为的进行操作更大的数拆分成小的数,从而得到与x相同的值,那对应与二进制为下的操作就是把更高的二进制为下的数拿过来,放到低位使用(就相当于做减法的时候,不够减退位一样)
  3. 我们可以把第一三种看做一种情况,把第二种情况我们用一个f来存储进位————思路就是这,具体看代码

代码

#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
#define ios ios::sync_with_stdio(false);
#define fre                          \
{                                    \
    freopen("A.txt", "r", stdin);   \
    freopen("Ans.txt", "w", stdout); \
}
const int mxn = 65;

ll num[mxn];

int main()
{
    /* fre; */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        ll m, n, sum = 0;;
        memset(num, 0, sizeof(num));
        scanf("%lld %lld", &m, &n);
        ll t;
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld", &t);
            sum += t;
            int s = 0;
            while(t > 1) s ++, t >>= 1; 
            num[s] ++;
        }
        if(sum < m)
        {
            printf("-1\n");
            continue;
        }

        ll f = 0;                      //表示前面的低二进制为满2进入到更高为,之后更高位上的数值
        ll ans = 0;
        for(int i = 0; i <= 62; i ++)
        {
            if((1LL << i) & m) f --;        //主要这里要使用 1LL 
            if(f < 0)
            {
                int lv = i;
                while(! num[lv]) num[lv ++] = 1;
                num[lv] --;
                ans += lv - i;
                f = 0;
            }

            f += num[i];
            f >>= 1;
        }
        printf("%lld\n", ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/106232344