文章目录
2020牛客暑期多校训练营(第十场)题解及补题
比赛过程
这场比赛只做了两个签到题,不是很理想,J题需要一点思维和树形dp以及二分图最大权匹配,I题是一个思维题,比赛的时候打表找到了一点规律但是没往那个方向深入的思考,有点遗憾。
题解
A
题意
生成一个1到 p − 1 p-1 p−1的排列,要求在模 p p p意义下满足 a i − 1 × 3 = a i a_{i-1}\times 3=a_{i} ai−1×3=ai或 a i − 1 × 2 = a i a_{i-1}\times 2=a_{i} ai−1×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] 2y−d[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 (