首页 > 其他分享 >Codeforces Round #843 (Div. 2)ACE 补D

Codeforces Round #843 (Div. 2)ACE 补D

时间:2023-01-12 11:46:59浏览次数:50  
标签:va vb 843 idx int Codeforces ++ && Div

A. Gardener and the Capybaras

题意:

给定一个由 ab 串,将该字符串拆分成 3 个部分,使中间部分的字典序最大或者最小。

分析:

  • 考虑简单的最小情况:中间只有一个 a ,两边总会 \(≥\) 中间;
  • 中间最大:若在中间无法找到 a ,说明中间全是 b ,这样不管第一个和最后一个字符是什么中间总大于两边
void solve()
{
    cin >> s;
    s = " " + s;
    int len = s.size() - 1;
    int pos = 0;
    for (int i = 2; i < len; i++)
    {
        if (s[i] == 'a')
        {
            pos = i;
            break;
        }
    }

    if (pos)
    {
        for (int i = 1; i < pos; i++)
            cout << s[i];
        cout << " a ";
        for (int i = pos + 1; i <= len; i++)
            cout << s[i];
        cout << endl;
    }
    else
    {
        cout << s[1] << " ";
        for (int i = 2; i < len; i++)
            cout << s[i];
        cout << " " << s[len];
        cout << endl;
    }
}

C. Interesting Sequence

题意:

给定 a b,求出大于 a 的最小的 num 使:
\(n\) & \(n+1\) & \(n+2\) & \(...\) & \(num\) \(=\) \(b\)

分析:

&运算只能使 1 变成 0,而不能使 0 变成 1,首先在二进制表示的 a 与 b 中,若 b 的第 k 位为 1 而 a 的第 k 位为 0 ,直接输出-1;
a 上数之后,a 中的 1 只会越来越少,不可能大于原来的数量;
在逐位分析:

  • ak = 0 && bk = 0,这一位就不用考虑
  • ak = 0 && bk = 1,不可能
  • ak = 1 && bk = 0,要在范围之内至少存在一个数的第 k 位为 1
  • ak = 1 && bk = 1,要在范围之内所有数的第 k 位都是 1

从高位开始考虑,所有发生情况 4 的位都是需要保留的位,发生情况 3 的位都是要通过 ++ 来使这一位与上 0,此时必定会将上一位的 1 变成 0 ,或将 0 变成 1 ,所以此时如果前一位是需要保留的位,直接FALSE,要保证需要保留的最低位比情况 3 发生的最高位高至少 2 位,此时,需要改变的最高位的前一位必定是 0,也是改变为 1 后最接近 a 的数

void solve()
{
    idxa = idxb = 0;
    cin >> a >> b;
    if (a < b)
    {
        cout << "-1" << endl;
        return;
    }
    if (a == b)
    {
        cout << a << endl;
        return;
    }

    int aa = a, bb = b;
    while (aa)
    {
        if (aa % 2)
            idxa++;
        aa /= 2;
    }
    while (bb)
    {
        if (bb % 2)
            idxb++;
        bb /= 2;
    }

    if (idxa < idxb)
    {
        cout << "-1" << endl;
        return;
    }
    else
    {
        vector<int> va, vb;
        while (a)
        {
            va.push_back(a % 2);
            a /= 2;
        }
        while (b)
        {
            vb.push_back(b % 2);
            b /= 2;
        }

        int maxsize = max(va.size(), vb.size());
        while (va.size() <= maxsize)
            va.push_back(0);
        while (vb.size() <= maxsize)
            vb.push_back(0);

        int ne = 100, ch = 100;
        bool f = true;
        for (int i = maxsize; i >= 0; i--)
        {
            if (va[i] == 1 && vb[i] == 1)
                ne = i;
            if (va[i] == 1 && vb[i] == 0 && ch == 100)
                ch = i;
            if (va[i] == 0 && vb[i] == 1)
            {
                cout << "-1" << endl;
                return;
            }
            if (va[i] == 1 && vb[i] == 0)
                f = false;
            if (!f && va[i] == 1 && vb[i] == 1)
            {
                cout << "-1" << endl;
                return;
            }
        }
        if (ch >= ne - 1)
        {
            cout << "-1" << endl;
            return;
        }

        int res = 0;
        for (int i = maxsize; i >= 0; i--)
        {
            if (va[i] == 1 && vb[i] == 1)
                res += pow(2, i);
            if (va[i] == 1 && vb[i] == 0)
            {
                res += pow(2, i + 1);
                break;
            }
        }

        cout << res << endl;
        return;
    }
}

E. The Human Equation

题意:

给定一个序列,每次操作先选择一个子序列,然后对奇数位置的数 +1,对偶数位置的数 -1,或对奇数位置的数 -1,对偶数位置的数 +1,求最少操作次数使得所有数变为 0

分析:

结论题QWQ(没想到)
选定随意区间进行操作,那么对于任意的区间和只有三种情况:+1,-1,不变
放到子序列上也对应这三种情况。。。
所以如果要把全部的区间和都变成 0 ,只要让需要的区间和变为 0

void solve()
{
    mst(s, 0);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
    }

    int minv = 0, maxv = 0;
    for (int i = 1; i <= n; i++)
    {
        maxv = max(maxv, s[i]);
        minv = min(minv, s[i]);
    }

    cout << maxv - minv << endl;
}

D. Friendly Spiders

题意:

n 个点,两辆不互质的点之间可以互相到达,给定 S 和 T ,求最短距离和路径

分析:

\(n^2\) 建图必 T ,这题首先分析数据范围,最多 3e5 的点,点最大也是 3e5 ,对这一范围内的数每个数分解因数是 \(nlogn\) ,任意两个不互质的数必定会连接到一个共同因数上去,若这个因数是质数那么他自己相当于‘根’,若这个数不是质数则会连到他的因数上去,最终所有数都被连接到自己的最小质因数上;
复杂度:线性筛,分解质因数 + 建双向边,dijkstra,记录路径
不考虑重边最后边数:\(2*nlogn\) ,拓展点数 + 总点数:\(n + logn\)
(本题若一开始建立带权边会 T ,由于边权的性质只有能到达和不能到达,所以可以在 dijkstra 更新距离时 +1 来优化)

#include <bits/stdc++.h>
using namespace std;
#define mst(x, y) memset(x, y, sizeof x)
#define endl '\n'
#define INF 0x3f3f3f3f
#define x first
#define y second
#define int long long
#define Lson u << 1, l, mid
#define Rson u << 1 | 1, mid + 1, r
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 2000010, MOD = 1e9 + 7;
const double EPS = 1e-6;
typedef pair<int, int> PII;
typedef unordered_map<int, int> Ump;
int S, T;
int n, a[N];
map<PII, bool> mp;
int pre[N];
int st[N], primes[N], cnt;
int h[N], e[N], ne[N], idx;
int d[N];
bool vis[N];
// void add(int a, int b, int c)
// {
//     e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
// }
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void get_primes()
{
    for (int i = 2; i < N; i++)
    {
        if (!st[i])
            primes[cnt++] = i, st[i] = i;
        for (int j = 0; primes[j] * i < N; j++)
        {
            st[primes[j] * i] = primes[j];
            if (i % primes[j] == 0)
                break;
        }
    }
}
int dijkstra(int S, int T)
{
    mst(d, 0x3f), mst(vis, false);
    d[S] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({d[S], S});

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int id = t.second, dist = t.first;

        if (vis[id])
            continue;
        vis[id] = true;

        for (int i = h[id]; ~i; i = ne[i])
        {
            int j = e[i];
            if (d[j] > dist + 1)
            {
                d[j] = dist + 1; // 优化
                heap.push({d[j], j});
                pre[j] = id;
            }
        }
    }

    if (d[T] > INF)
        return -1;
    return d[T];
}

void solve()
{
    mst(h, -1);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> S >> T;
    if (S == T)
    {
        cout << 1 << endl
             << S << endl;
        return;
    }
    if (a[S] == a[T])
    {
        if (a[S] == 1)
        {
            cout << -1 << endl;
            return;
        }
        cout << 2 << endl;
        cout << S << " " << T << endl;
        return;
    }

    for (int i = 1; i <= n; i++)
    {
        for (int j = a[i]; j >= 2; j /= st[j])
        {
            if (mp[{i, st[j]}])
                continue;
            // cout << i << " " << st[j] << endl;
            add(i, st[j] + n);
            add(st[j] + n, i);
            mp[{i, st[j]}] = true;
        }
    }

    int res = dijkstra(S, T);
    // cout << res << endl;

    if (res == -1)
        cout << "-1" << endl;
    else
    {
        vector<int> road;
        int cur = T;
        while (cur != S)
        {
            if (cur <= n)
                road.push_back(cur);
            cur = pre[cur];
        }
        road.push_back(S);

        cout << road.size() << endl;
        reverse(road.begin(), road.end());
        
        for (auto t : road)
            cout << t << " ";
        cout << endl;
    }
}
signed main()
{
    FAST;
    get_primes();
    solve();
    return 0;
}

标签:va,vb,843,idx,int,Codeforces,++,&&,Div
From: https://www.cnblogs.com/Aidan347/p/17044386.html

相关文章

  • Codeforces Edu Round 106 Div2
    解题A.DominoonWindowsill这个题给一个2xn的方格,一个行有k1个白块,第二行有k2个白块,那么现在有w个2x1的白块和b个2x1黑块,白对白,黑对黑,问能不能全放下这个就是判断下白......
  • 818 Div 2.F. Madoka and The First Session
    Problem-F-Codeforces818Div2.F.MadokaandTheFirstSession思路:不妨转化一下题意:将条件转化为:\(b_v+1,b_v+1\),然后使得其中一个-2那么在\(a\)上就是使\(a_......
  • [Codeforces Round #822 (Div. 2)](https://codeforces.com/contest/1734)
    CodeforcesRound#822(Div.2)ProblemF.ZerosandOnes解法定义:\(f(x)\)为在\(S\)串中位置为\(x\)的值。显然\(f(x)\in0,1\)有一重要性质:若\(f(x)\)为1,那么二进制......
  • Codeforces Round #843 (Div. 2)
    Preface难得的7点场CF,结果反而遇上了我最困的时候(吃完晚饭血糖上来就贼困,我一般反而凌晨场比较清醒)但是这场表现还可以,写的题基本都是一发入魂而且速度也比较快比较可惜......
  • 【Codeforces 173B】 B. Chamber of Secrets
    【Codeforces173B】B.ChamberofSecretshttps://codeforces.com/problemset/problem/173/B题意+分析来自\(OI-wiki\)这题主要难度就是读题...还有注意初始方向......
  • Codeforces Round #843 (Div. 2)
    A-GardenerandtheCapybaras题意给出字符串S,S只由字符a,b组成,问怎么切分可以使字符串分为小大小,大小大这种的三段。思路在2~n-1的范围内找到字符a的位置,如果里......
  • Codeforces Round #843 (Div. 2)
    题目链接Atag:构造,分类讨论核心思路我们其实可以发现我们要是分很多情况去讨论abc,这题就不好做。所以我们可以假设a和b就是我们字符串的两个端点,这样题目就很好做了......
  • Codeforces Round #843 (Div. 2) Problem C
    C.InterestingSequencetimelimitpertest1secondmemorylimitpertest256megabytesinputstandardinputoutputstandardoutput  Petyaandhisfr......
  • Codeforces 1278 F Cards 增强版 题解 (斯特林数,推式子)
    原题链接增强版链接增强版中k=1e7为啥网上题解的式子都那么长啊.jpg首先令\(p=\frac1m\)。求某个数的次幂的题通常都是无脑转下降幂:\(x^k=\sum_{i=0}^kS_2(k,i)x^{\u......
  • Codeforces Round #823 (Div. 2)
    A.B.C.DCodeforcesRound#823(Div.2)A.Planets-签到题意题意是一些卫星在一些轨道上,操作1花费1摧毁一个卫星,操作2花费\(y\)摧毁一个轨道上的所有卫星,问摧......