2021“MINIEYE杯”中国大学生算法设计超级联赛(6)

2021“MINIEYE杯”中国大学生算法设计超级联赛(6)

1001.Yes, Prime Minister

  • 题意

给出一个数x ((-10^7 <= x _i <= 10^7)) 让你求出最小的一对(l,r)且((l <= x_i <= r)) 中 ((sum_{i=l}^r i)) 为质数。

  • 思路

推了一会就开始打表了,打了个表规律就非常的清晰了。

  1. 一个正数x,要么自己的质数,要么(2 * x + 1) | (2 * x - 1)是质数,要么就直接从-x到x,之后在一直找大于x的同性质成立的质数就行了,两个质数之间距离 / 2相差应该不大,之间暴力找就行了
  2. 负数-x,直接先加到x变成0,之后往后面找一个为质数或两个相加为质数的情况即可

code :

void solve()
{
    int n;
    cin >> n;
    int ans = 0;
    if (n <= 0)
    {
        if (n == 0)
            cout << "3" << endl;
        else
        {
            int x = abs(n) + 1;
            int res = 0;
            for (int i = 0; i <= 60; i++)
            {
                int y = x + i;
                if (!st[y])
                {
                    cout << 2 * y << endl;
                    return;
                }
                if (!st[2 * y + 1])
                {
                    cout << 2 * y + 1 << endl;
                    return;
                }
            }
        }
    }
    else
    {
        if (!st[n])
            cout << "1" << endl;
        else
        {
            int res = 0;
            int x = n;
            if (!st[2 * x - 1] || !st[2 * x + 1])
            {
                cout << "2" << endl;
                return;
            }
            for (int i = 1; i <= 60; i++)
            {
                int y = x + i;
                if (!st[y])
                {
                    cout << 2 * y << endl;
                    return;
                }
                if (!st[2 * y + 1])
                {
                    res = (2 * y + 1);
                    cout << res << endl;
                    return;
                }
            }
        }
    }
}

1004.Decomposition

  • 题意

给你n个点形成的完全图,让你去将他分成k个简单图,每个简单图中,你需要有(l_i)条路径,而且,每个简单图中的顶点都是两两不同的。

  • 思路

看懂题意后,其实就是一道构造题。
然后,你通过不断构造可以发现用欧拉回路去构造是完美的,然后你可以去欧拉回路中以每个点为起点进行增加边,题目说了最多(sumlimits_{i=1}^k l_i = frac{n(n-1)}{2})条边,那么只需要 (frac{n}{2} * n)个点放进去就够了,直接输出存起来的边即可。

code:

vector<int> ege;
int ST;
void solve(){
    cout << "Case #" << ++ST << ":" << endl;
    ege.clear();
    int n,k;
    cin >> n >> k;
    ege.pb(n - 1);
    for(int i = 0;i <= n / 2;i ++) {
        int sgn = 1, now = i;
        for(int j = 1;j < n;j ++) {
            ege.pb(now);
            // 欧拉回路中交替构造边
            now = (now + sgn * j + n - 1) % (n - 1);
            sgn *= -1;
        }
        ege.pb(n - 1);
    }
    int now = 0;
    while(k --) {
        int len;
        cin >> len;
        len ++;
        while(len --) cout << ege[now ++] + 1 << (len?' ':'
');
        now --;
    }
}

1005.Median

  • 题意

给出n,m, 并给出m个(b_i), 需要构造一个数组c,并且分割m个区间后,每个区间的中位数都是(b_i), 且数组C是由1,2 ··· n构成的,且唯一,你需要判断能否构造出这样的数组C

  • 思路

直接找不为中位数的点,且把每段连续的点都存在不同的vector里,然后判断最长的段的大小和其他的大小进行相比。

  1. 如果这个最长的段小于其他的段,直接那么就一定存在解,输出yes即可
  2. 否则,最后剩下max(块) - sum(其他),然后遍历一遍中位数,记录小于这个块的最小值的中位数的数量cnt,然后比较 cnt 和 上面的剩下的即可。

code :

vector<vector<int> > v;
int a[N];
int st[N];

int cnt;
void solve(){
    int n,m;
    cin >> n >> m;
    v.resize(m + 2);
    for(int i = 1;i <= cnt;i ++) v[i].clear();
    cnt = 1;
    for(int i = 1;i <= n;i ++) st[i] = 0;
    
    for(int i = 1;i <= m;i ++) {
        cin >> a[i];
        st[a[i]] = 1;
    }
    for(int i = 1;i <= n;i ++) {
        if(!st[i]) {
            v[cnt].push_back(i);
        }else if(v[cnt].size()){
            cnt ++;
        }
    }
    int maxn = 0;
    int sum = 0;
    int id = 0;
    for(int i = 1;i <= cnt;i ++) {
        int k = v[i].size();
        if(maxn < k) {
            id = i;
            maxn = k;
        }
        sum += k;
    }
    sum -= maxn;
    if(n == m) {
        cout << "YES" << endl;
        return;
    }
    if(maxn < sum) {
        cout << "YES" << endl;
        return;
    }
    maxn -= sum;
    int res = 0;
    for(int i = 1;i <= m;i ++) {
        if(a[i] < v[id][0]) res ++;
    }
    if(res >= maxn) {
        cout << "YES" << endl;
    }else {
        cout << "NO" << endl;
    }
}

原文地址:https://www.cnblogs.com/darker-wxl/p/15105258.html