Codeforces Round #587 (Div. 3) 比赛&补题

1216A. Prefixes

题意

给一个字符串,长度为偶数,只包含小写字母a和b,你可以变换其中任意一个字母,把a换成b或者把b换成a。要求最后结果中的字符串任意偶数前缀a和b的数量相同。

题解

只需要保证第i个字母和第i+1个字母不相同就行了,i每次递增2。

代码

#include<bits/stdc++.h>

using namespace std;
const int maxn = 31;

int main()
{
    string s;
    int n, ans=0;
    cin >>n >>s;

    for(int i=0; i<n-1; i+=2)
    {
        if(s[i]==s[i+1])
        {
            if(s[i]=='a')
                s[i] = 'b';
            else
                s[i] = 'a';
            ans++;
        }
    }

    cout <<ans <<endl;
    cout <<s <<endl;

    return 0;
}

1216B. Shooting

题意

给你几个罐子,每个罐子的耐久度为ai,你要将所有罐子击碎,当你要击碎第i个罐子时,你需要射击(ai*x+1)次,其中x为你已经击碎的罐子,可认为你将一个罐子击碎才会去射击下一个罐子。

题解

x是重点,只要反向排一下序就行了,有些类似哈夫曼树。一开始以为最后让依次输出第i个罐子是第几次被射击的,后来WA了一次才发现是让依次输出射击的是第几个罐子。。。

代码

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1000+10;

struct A
{
    int ai, index;
}ax[maxn];

bool cmp1(A a, A b)
{
    return a.ai>b.ai;
}


int main()
{
    int n;
    cin >>n;
    for(int i=0; i<n; i++)
    {
        cin >>ax[i].ai;
        ax[i].index = i+1;
    }
    int x=0, ans=0;
    sort(ax, ax+n, cmp1);

    for(int i=0; i<n; i++)
    {
        ans+=(ax[i].ai*x+1);
        x++;
    }

    cout <<ans <<endl;
    cout <<ax[0].index;
    for(int i=1; i<n; i++)
        cout <<' ' <<ax[i].index;
    cout <<endl;

    return 0;
}

1216C. White Sheet

题意

给你一个白纸的左下角和右上角坐标,还有两张黑纸的左下角和右上角坐标,保证这三张纸的边缘都平行于坐标轴,问你黑纸是否能完全覆盖住白纸。

题解

坐标范围1e6,可以依次遍历白纸边缘的每一个点,看他是否在黑纸内,递增要设成0.5,不能设成1,最后没时间了,不知道思路对不对,回来再来补吧。(补:果然过了,太智障了。。。)

代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5+10;

int main()
{
    int x1, y1, x2, y2;
    int x3, y3, x4, y4;
    int x5, y5, x6, y6;
    cin >>x1 >>y1 >>x2 >>y2;
    cin >>x3 >>y3 >>x4 >>y4;
    cin >>x5 >>y5 >>x6 >>y6;

    for(double i=x1; i<=x2; i+=0.5)
    {
        if((i<=x4&&i>=x3&&y1<=y4&&y1>=y3) || (i<=x6&&i>=x5&&y1<=y6&&y1>=y5))
            continue;
        else
        {
            cout <<"YES" <<endl;
            return 0;
        }
    }

    for(double i=y1; i<=y2; i+=0.5)
    {
        if((i<=y4&&i>=y3&&x1<=x4&&x1>=x3) || (i<=y6&&i>=y5&&x1<=x6&&x1>=x5))
            continue;
        else
        {
            cout <<"YES" <<endl;
            return 0;
        }
    }

    for(double i=x2; i>=x1; i-=0.5)
    {
        if((i<=x4&&i>=x3&&y2<=y4&&y2>=y3) || (i<=x6&&i>=x5&&y2<=y6&&y2>=y5))
            continue;
        else
        {
            cout <<"YES" <<endl;
            return 0;
        }
    }
    for(double i=y2; i>=y2; i-=0.5)
    {
        if((i<=y4&&i>=y3&&x2<=x4&&x2>=x3) || (i<=y6&&i>=y5&&x2<=x6&&x2>=x5))
            continue;
        else
        {
            cout <<"YES" <<endl;
            return 0;
        }
    }

    cout <<"NO" <<endl;

    return 0;
}

1216D. Swords

题意

地下室有n种剑,每种剑有x个,有y个人来地下室偷剑,每个人只拿一种剑,每个人拿了z个剑。现在发现地下室的剑被偷了,每种剑剩下ai个,其中x, y, z未知,给出n和ai,让你求出最少y个人来偷剑和每个人偷了多少剑z。

题解

用最大的数依次减去其他所有ai,求他们所有的最大公因数,然后再用前面算出来的最大数和其他数的差除以最大公因数,则可算出有多少人来偷剑了,最大公因数即为每个人偷了多少剑。

代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int a[maxn];
stack<int> s, ss;

bool cmp(int x, int y)
{
    return x>y;
}

int main()
{
    int n;
    scanf("%d", &n);
    for(int i=0; i<n; i++)
        scanf("%d", &a[i]);
    sort(a, a+n, cmp);
    int x, y;
    for(int i=1; i<n; i++)
    {
        x = a[0]-a[i];
        if(x)
        {
            s.push(x);
            ss.push(x);
        }
    }
    while(s.size()>1)
    {
        x = s.top();
        s.pop();
        y = s.top();
        s.pop();

        s.push(__gcd(x, y));
    }

    ll ans=0;
    while(!ss.empty())
    {
        x = ss.top();
        ss.pop();
        ans+=(x/s.top());
    }

    printf("%lld %d\n", ans, s.top());

    return 0;
}

1216E1. Numerical Sequence (easy version)

题意

11212312341234512345612345671234567812345678912345678910......,给你一个这样的无限循环数列,1、12、123、1234、12345......这样循环,询问q次,每次询问在这个数列中第k位是什么数字。注意:11算两位数字,而不是一个数字。k最大为1e9,q不大于100。

题解

由程序算出当k为1e9时总共也才21837个数,所以我们只用预处理出前1e5个数的排列,预处理时记录下每个数的最后一位排到哪里了,最后直接查表就行了。

计算程序:

ll k=0, i=1, x;
    while(k<=1000000000){
        for(ll j=1; j<=i; j++){
            x = j;
            while(x){k++;x/=10;}
        }
        i++;
    }

代码

#include <iostream>
#include <queue>
#include <string.h>

#define ll long long

using namespace std;
const int maxn = 1e5+10;
int num[maxn*5], pre[maxn], n;

inline void cal(int x)
{
    if(!x)
        return;
    cal(x/10);

    num[++n] = x%10;
    return;
}

int main()
{
    int x;
    n = 0;
    for(int i=1; i<=100000; i++)
    {
        cal(i);
        pre[i] = n;
    }

    int q;
    ll k;
    cin >>q;

    while(q--)
    {
        cin >>k;
        ll sum=0;

        for(int i=1; i<100000; i++)
        {
            if(sum+pre[i]<k)
                sum+=pre[i];
            else
            {
                cout <<num[k-sum] <<endl;
                break;
            }
        }
    }

    return 0;
}

参考

准点的星辰Codeforces Round #587(Div.3)

posted @ 2021-02-24 16:38  zhangzeff  阅读(56)  评论(0)    收藏  举报