2020牛客暑期多校训练营(第十场)A、C、D、E、I、J题解及补题

2020牛客暑期多校训练营(第十场)题解及补题

比赛过程

这场比赛只做了两个签到题,不是很理想,J题需要一点思维和树形dp以及二分图最大权匹配,I题是一个思维题,比赛的时候打表找到了一点规律但是没往那个方向深入的思考,有点遗憾。

题解

A

题意

生成一个1到 p − 1 p-1 p1的排列,要求在模 p p p意义下满足 a i − 1 × 3 = a i a_{i-1}\times 3=a_{i} ai1×3=ai a i − 1 × 2 = a i a_{i-1}\times 2=a_{i} ai1×2=ai

解法

乘2操作会划分出好几个环,乘3显然在环之间转移,所以暴力搞乘2不行就乘3。

代码
#include <stdio.h>

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
#include <vector>
using namespace std;
typedef long long ll;
#define P pair<ll, ll>
const ll maxn = 1e5 + 111;
int a[maxn];
int main() {
   
    int T;
    scanf("%d", &T);
    while (T--) {
   
        int n;
        scanf("%d", &n);
        vector<int> vis(n + 2, 0);
        vector<int> ans;
        vis[1] = 1;
        ans.push_back(1);
        int la = 1;
        int flag = 1;
        for (int i = 2; i < n; ++i) {
   
            int tp = la * 2 % n;
            if (vis[tp]) {
   
                tp = la * 3 % n;
                if (vis[tp]) {
   
                    flag = 0;
                    break;
                }
            }
            vis[tp] = 1;
            ans.push_back(tp);
            la = tp;
        }
        if (!flag) {
   
            puts("-1");
            continue;
        }
        int rr = ans.size();
        for (int i = 0; i < rr; ++i) {
   
            printf("%d%c", ans[i], i < rr - 1 ? ' ' : '\n');
        }
    }
    return 0;
}

B

题意
解法
代码
//将内容替换成代码

C

题意

有一棵 n n n 个结点的树,每次可以选择两个点,并使路径上所有边的权值减一,问最少需要操作几次使得所有边的权值变成 0 0 0 。并且有 m m m 次询问,每次修改一个边的权值,每次询问输出当前的结果。

解法

首先把边上的权值转换成点的权值,边上的权值减一就是边的两个端点的权值减一。所以问题就转换成了最少访问点的次数,使所有点的权值变为 0 0 0

我们可以画图观察点,然后可以推出一个简单易得的结论,如果一个点连接的边中,最大权值小于这个点连接的边权总和的一半,那么这个点所连接的这些边可以通过操作变为0

所以,我们需要判断边权总和d[x]的奇偶:

  • d[x]为奇,就只要再访问一次,消去剩余的那 1 1 1 边权;
  • d[x]为偶,我们就再加上 2 y − d [ x ] 2y-d[x] 2yd[x] 次访问,来消去不能与这个点其他相连的边消去的部分。
代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
namespace fastIO {
   
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
   
    static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    if (p1 == pend) {
   
        p1 = buf;
        pend = buf + fread(buf, 1, BUF_SIZE, stdin);
        if (pend == p1) {
   
            IOerror = 1;
            return -1;
        }
    }
    return *p1++;
}
inline bool blank(char ch) {
    return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
   
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
        x = x * 10 + ch - '0';
    if (sign)
        x = -x;
    return true;
}
inline bool R(double &x) {
   
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值