寒假训练第九天-Codeforces Round #696 (Div. 2)

寒假训练第九天-Codeforces Round #696 (Div. 2)

前言:快乐的一天从补cf开始。

题目链接-https://codeforces.com/contest/1474

A-Puzzle From the Future

题意:读了半天没读懂啥意思,心态就崩了。就是说现在有两个01串,将两个01串按位相加后得到一个只含012的串(长度不变),所得的串相邻字母若相同则只保留一个(即化简后),现在给你一个01串,问另一个串是什么才能使按位相加并简化后的串最大(比较大小按去除前缀0的比较)。

题解:由题意我们很容易明白要使最后得到的串最大,那相加后肯定不能有相邻的字母相等,因为化简后会降位,所以我们可以根据前一个输出的是什么去选择不同于前一个的最大的数即可。

string s;
int32_t main()
{
    
    
    ICO;
    int t, n;
    cin >> t;
    while(t--)
    {
    
    
        cin >> n >> s;
        int p = 0;
        for(int i = 0; i < n; i++)
        {
    
    
            if(p == 0) {
    
    cout << 1; p = s[i] - '0' + 1;}
            else if(p == 1)
            {
    
    
                if(s[i] == '0') {
    
    cout << 0; p = 0;}
                else {
    
    cout << 1; p = 2;}
            }
            else
            {
    
    
                if(s[i] == '0') cout << 1;
                else cout << 0;
                p = 1;
            }
        }
        cout << endl;
    }
    return 0;
}

B-Different Divisors

题意:给你一个数d,必然存在满足下面两个条件的数x:1、至少有4个因子 2、每个因子之间至少相差d。求满足条件的最小x。

题解:可以先将范围内的素数筛出来,然后查找两个素数a,b即可,则x为a * b(4个因子分别为1,a,b,a * b )。

bool book[22000];
int prime[4000], cnt = 1;
int32_t main()
{
    
    
    ICO;
    for(int i = 2; i <= 21000; i++)
    {
    
    
        if(!book[i]) prime[cnt++] = i;
        for(int j = 1; j < cnt; j++)
        {
    
    
            if(i * prime[j] > 21000) break;
            book[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
    int t, d;
    cin >> t;
    while(t--)
    {
    
    
        cin >> d;
        int p = upper_bound(prime + 1, prime + cnt, 1 + d) - prime;
        if(prime[p - 1] == 1 + d) p--;
        int q = upper_bound(prime + p, prime + cnt, prime[p] + d) - prime;
        if(prime[q - 1] == prime[p] + d) q--;
        cout << prime[p] * prime[q] << endl;
    }
    return 0;
}

C-Array Destruction

题意:给你一个数组,每次删除两个数,要求两个数的和等于上一次删除的两个数中较大的数,问第一次删除前是否存在一个数t使得第一次删除的和是t,输出x和每次删除的两个数。

题解:首先我们可以枚举t,t肯定是原数组的最大值和原数组中的另一个数的和,所以我们需要没举(2 * n - 1)次。每一次我们用一个数组去维护每次删除后的数,假设我们现在要删除两个数,则删除的其中一个数必须是数组中的最大值(易证若不是最大值,则最大值会一直留到最后无法删除),然后我们在维护的数组中去二分查找另一个数,若找不到,则该t不符合,若找的到就将该数从维护的数组中删除即可,然后进行下一步的删除,直到维护的数组为空(全部删除)即可。

int a[2010];
int32_t main()
{
    
    
    ICO;
    int t, n;
    cin >> t;
    while(t--)
    {
    
    
        cin >> n;
        for(int i = 1; i <= (n << 1); i++) cin >> a[i];
        sort(a + 1, a + 1 + (n << 1));
        bool ok;
        for(int i = 1; i < (n << 1); i++)
        {
    
    
            ok = 1;
            int t = a[n << 1] + a[i];
            int tt = t;
            vector<int> ve, res;
            for(int j = 1; j <= (n << 1); j++) ve.push_back(a[j]);
            for(int j = 0; j < n; j++)
            {
    
    
                auto it = ve.end();
                int x = t - *(--it);
                ve.erase(it);
                if(binary_search(ve.begin(), ve.end(), x) == 0) {
    
    ok = 0; break;}
                res.push_back(t - x), res.push_back(x);
                t = max(t - x, x);
                it = upper_bound(ve.begin(), ve.end(), x);
                ve.erase(--it);
            }
            if(ok)
            {
    
    
                cout << "YES" << endl << tt << endl;
                for(int j = 0; j < res.size(); j += 2) cout << res[j] << ' ' << res[j + 1] << endl;
                break;
            }
        }
        if(!ok) cout << "NO" << endl;
    }
    return 0;
}

总结:C题花时间太长了,刚开始用lower_bound删it就导致查找数非常小时会出现错误。后来改了upper就好了。

猜你喜欢

转载自blog.csdn.net/Siyue1999/article/details/112908114