Codeforces Round 889 (Div. 2) 赛后总结

小菜鸡的赛后总结

小总结

  • 这一次算是目前本萌新状态最好的一次了.....希望之后能再接再厉,代码还太臃肿了,总之加油吧!为了热爱的东西!

B. Longest Divisors Interval

  • 题意:给出一个整数n,求可以被n整除的最长连续区间的长度
  • 思路:根据样例猜答案,发现从1开始找就行了,遍历到第一个不能被整除的数字就退出输出
void BlueFire()
{
    ll n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        if (n % i != 0)
        {
            cout << i - 1 << endl;
            return;
        }
    cout << n << endl;
    return;
}

C1. Dual (Easy Version)

  • 题意:给出一个数组,可以对这个数组中的数作一个操作:选择编号为i和j的两个数,让ai变为ai + aj,也就是把编号j的数加到编号i的数上。要求在50次操作内将该数组变为非递减,输出操作次数和每次操作的i,j
  • 思路:简单版本比较好做,对于全正和全负的数组,只需要对全正求一遍前缀和,全负求一遍后缀和即可,而对于有正有负的数组,观察数据范围可以发现数组中的每个数都是在-20和20之间的,又发现如果每次操作i = j,那么做了k次这样的操作其实就是让这个数乘上2的k次方,2的5次方就大于20了,所以直接随便选一个正数,让它乘上2的5次方(这里我直接乘了8次方),然后把它加到最后一位数,从第一位开始,每位加一次最后一位,然后最后一位又乘2一次,又加下一位....还是比较暴力的,这样下来操作次数也小于50次
void BlueFire()
{
    int n;
    cin >> n;
    vector<int> a(25);
    int neindex = 0;
    int poindex = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] < 0 && neindex == 0)
            neindex = i;
        if (a[i] > 0 && poindex == 0)
            poindex = i;
    }
    if (neindex == 0 && poindex == 0)
    {
        cout << 0 << endl;
        return;
    }
    int op = 0;
    if (neindex == 0)
    {
        cout << n - 1 << endl;
        for (int i = 1; i < n; i++)
        {
            cout << i + 1 << " " << i << endl;
        }
 
        return;
    }
    if (poindex == 0)
    {
        cout << n - 1 << endl;
        for (int i = n; i > 1; i--)
            cout << i - 1 << " " << i << endl;
        return;
    }
    cout << 2 * (n - 1) + 10 << endl;
    for (int i = 1; i <= 8; i++)
        cout << poindex << " " << poindex << endl;
    cout << n << " " << poindex << endl;
    poindex = n;
    cout << poindex << " " << poindex << endl;
    for (int i = 1; i < n; i++)
    {
        cout << i << " " << poindex << endl;
        cout << n << " " << n << endl;
    }
    return;
}

C2. Dual (Hard Version)

  • 题意:与上一题相同,但操作次数限制在了31次
  • 思路:这一次可不能那么暴力了,对于有正有负的,可以尝试将这个数组变成全负或者全正来计算,这样前缀和用掉了n-1次,最坏情况下(20个数)是19次,还剩下12次,这时候我分成了两种情况:
    1.正数和负数出现的次数都大于8次,也就是8+12,9+11,10+10这三种情况,这样的话我们直接看最大的正数和最小的负数,拿绝对值较大的那个去加那些与它符合相反的,这下最坏也刚好12次满
    2.正数和负数出现的次数有一方小于8次,那么我们直接让出现次数多的那个符合的数,选其中最大的(其实随便一个就行)乘2的五次方,再去加那些与它符合相反的,这下最坏也刚好12次(5 + 7)
    进行完这些操作后,再执行一遍全负和全正的前缀和就行了!
int n;
void qf()
{

    for (int i = n; i > 1; i--)
        cout << i - 1 << " " << i << endl;
    return;
}
void qz()
{

    for (int i = 1; i < n; i++)
        cout << i + 1 << " " << i << endl;
    return;
}
void BlueFire()
{
    cin >> n;
    vector<int> a(25);
    vector<int> pos;
    vector<int> neg;
    int pos_num = 0;
    int neg_num = 0;
    int maxPos = 0;
    int minNeg = 99;
    int maxPos_index = 0;
    int minNeg_index = 0;
    int zeros = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] > 0)
        {
            pos_num++;
            if (a[i] > maxPos)
            {
                maxPos = a[i];
                maxPos_index = i;
            }
            pos.push_back(i);
        }
        else if (a[i] < 0)
        {
            neg_num++;
            if (a[i] < minNeg)
            {
                minNeg = a[i];
                minNeg_index = i;
            }
            neg.push_back(i);
        }
        else
        {
            zeros++;
            pos.push_back(i);
        }
    }
    if (zeros == n)
    {
        cout << 0 << endl;
        return;
    }
    if (pos_num == 0)
    {
        cout << n - 1 << endl;
        qf();
        return;
    }
    if (neg_num == 0)
    {
        cout << n - 1 << endl;
        qz();
        return;
    }
    pos_num += zeros;
    if (pos_num >= 8 && neg_num >= 8)
    {

        if (maxPos >= abs(minNeg))
        {
            cout << (n - 1) + (neg_num) << endl;
            for (int i = 0; i < neg.size(); i++)
            {
                cout << neg[i] << " " << maxPos_index << endl;
            }
            qz();
        }
        else
        {
            cout << (n - 1) + (pos_num) << endl;
            for (int i = 0; i < pos.size(); i++)
            {
                cout << pos[i] << " " << minNeg_index << endl;
            }
            qf();
        }
    }
    else
    {
        cout << (n - 1) + 5 + min(pos_num, neg_num) << endl;
        if (pos_num > neg_num)
        {
            for (int i = 1; i <= 5; i++)
                cout << maxPos_index << " " << maxPos_index << endl;
            for (int i = 0; i < neg.size(); i++)
                cout << neg[i] << " " << maxPos_index << endl;
            qz();
        }
        else
        {
            for (int i = 1; i <= 5; i++)
                cout << minNeg_index << " " << minNeg_index << endl;
            for (int i = 0; i < pos.size(); i++)
                cout << pos[i] << " " << minNeg_index << endl;
            qf();
        }
    }
    return;
}
posted @ 2023-07-30 21:19  布鲁诺邦古耐夫  阅读(134)  评论(0)    收藏  举报