Codeforces Round 1007 (Div. 2) 补题

比赛主页

目录

B. Perfecto

原题:B. Perfecto

题意:

构造一个长度为 n 的排列,满足从 1 到 n 的所有位置的前缀和都不是完全平方数。

如果不行,输出 -1.

思路:

如果直接构造 1,2,3,4,......,n,为什么有的位置不满足条件?

  1. 首先判断 [1,n] 的累加和是否是完全平方数

  2. 否则,遍历序列,不满足条件的位置跟它的下一个位置交换,即 swap ( a[i], a[i+1])

    • i 一定不会是最后一个位置,如果 i 是最后一个位置(即 n ),那么就是第 1 种情况了。
//      https://codeforces.com/contests/2071/problem/B
//      首先构造递增序列,再判断哪些位置不能满足条件,就跟它后面位置的数交换位置
//      如果 [1,i]位置不能满足条件,那么 i 位置一定不是最后一个位置
//      因为我们会首先判断长度为 n 的排列的全部和是否满足条件,不满足就是 -1,退出了

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m;
void solve()
{
    cin >> n;
    int temp = n * (n + 1) / 2;
    if ((int)sqrt(temp) * (int)sqrt(temp) == temp)
    {
        cout << -1 << "\n";
        return;
    }
    vector<int> ans(n);
    for (int i = 0; i < n; i++)
        ans[i] = i + 1;
    int sum = 0;
    for (int i = 0; i < n - 1; i++)
    {
        sum += ans[i];
        if ((int)sqrt(sum) * (int)sqrt(sum) == sum)
        {
            swap(ans[i], ans[i + 1]);
            sum -= ans[i + 1], sum += ans[i];
        }
    }
    for (int i : ans)
        cout << i << " ";
    cout << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

C. Trapmigiano Reggiano

原题:C. Trapmigiano Reggiano

题意:

给定一棵树,以及起点和终点,问是否能构造一个排列,一只老鼠从起点开始,按排列的位置走,最后确切的停在终点。

  • 一次只能走一步,比如说现在在 i 结点,p[x] = j,那么就往 j 结点那个方向走一步,不是到达 j 结点;
  • 如果 p[x] = i,那么就不动。

思路:

将这棵树看成以终点节点为根节点,层序遍历输出结点编号就是答案。

  • dfs
  • bfs
//      https://codeforces.com/contests/2071/problem/C
//      将树看成以 end 为根节点的树,按每一层的深度降序输出每一层的节点
//      就是层序遍历的逆顺序

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m;
int vis[100005];
void dfs(vector<vector<int>> &g, vector<vector<int>> &dis, int cur, int h)
{
    dis[h].push_back(cur); // 高度为 h 的那层新增节点 cur
    for (int next : g[cur])
    {
        if (vis[next] == 0)
        {
            vis[next] = 1;
            dfs(g, dis, next, h + 1);
            vis[next] = 0;
        }
    }
}

void bfs(vector<vector<int>> &g, int e)
{
    queue<int> que;
    que.push(e);
    vector<int> ans;
    while (!que.empty())
    {
        int head = que.front();
        que.pop();
        if (vis[head] == 1)
            continue;
        ans.push_back(head);
        for (int next : g[head])
        {
            if (vis[next] == 0)
                que.push(next);
        }
        vis[head] = 1;
    }
    for (auto it = ans.rbegin(); it != ans.rend(); it++)
        cout << *it << " ";
    cout << "\n";
}

void solve()
{
    int s, e;
    cin >> n >> s >> e;
    for (int i = 0; i <= n; i++)
        vis[i] = 0;
    vector<vector<int>> g(n + 1);
    for (int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    // bfs(g, e);

    vector<vector<int>> dis(n + 1); // 记录第 i 层有哪些节点
    vis[e] = 1;
    dfs(g, dis, e, 0);
    for (int i = n; i >= 0; i--)
    {
        for (int v : dis[i])
            cout << v << " ";
    }
    cout << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

D1. Infinite Sequence (Easy Version)

原题:D1. Infinite Sequence (Easy Version)

题意:

给定长度为 n 的二进制数组,以及 m,index,如果 m > n 那么 a[m] = a[1] ⊕ a[2] ⊕ ... ⊕ a[m/2]。(异或)

求 a [index] 是多少?

思路:

异或满足以下性质:

  • a ⊕ b = b ⊕ a
  • a ⊕ a = 0

设 [1, n] 位置的异或和结果为 res;

m / 2 就是向下取整,那么对于 m > n 位置的数,假设 m 为偶数,那么 a [m+1] = a [m];所以 [n, m/2 ] 区间里的成对的奇偶数异或之后就是 0,被抵消掉了;所以只需要判断 m/2 是不是偶数位置

  • m/2 位置是奇数,那么可以跟前面的偶数位置抵消,a [m] = res;
  • m/2 位置是偶数,那么 a [m] = res ⊕ a [m/2],那就递归地求 a [m/2],如果 m/2 <= n 了,那就返回 [1, m/2] 的异或结果

另外如果 n 是偶数,那么 n+1 就是奇数,不能抵消,所以需要单独判断一下,将 res 的值异或上 a [n+1]

//      https://codeforces.com/contest/2071/problem/D1
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, res;
int a[200005];
int p[200005];
int fun(int i)
{
    if (i / 2 <= n)
        return p[i / 2];
    if ((i / 2) & 1)
        return res;
    else
        return res ^ fun(i / 2);
}

void solve()
{
    int l, r;
    cin >> n >> l >> r;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (i == 1)
            p[i] = p[0] = a[i];
        else
            p[i] = p[i - 1] ^ a[i];
    }
    res = p[n];
    if (n % 2 == 0)
        res ^= p[n / 2], p[n + 1] = res;
    if (r <= n)
    {
        cout << a[r] << "\n";
        return;
    }
    if (r & 1)
        r--;
    cout << fun(r) << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}
posted @   明天天晴KKK  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示