A - Dawid and Bags of Candies
水题直接上代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define sz sizeof
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAX = 1e4 + 10;
int a[10];
int main() {
int N = 4, sum = 0;
for (int i = 1; i <= N; i++)
scanf("%d", &a[i]), sum += a[i];
sort(a + 1, a + 1 + N);
if (sum % 2) cout << "NO" << endl;
else {
int t = sum / 2;
if (a[4] == t || a[1] + a[4] == t) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
B - Ania and Minimizing
水题直接上代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define sz sizeof
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAX = 2e5 + 10;
int N, K;
char s[MAX];
int main() {
scanf("%d%d%s", &N, &K, s + 1);
int cnt = 0;
for (int i = 1; i <= N; i++) {
if (cnt < K) {
if (i == 1) {
if (N != 1) printf("1");
else printf("0");
if (s[1] != '1')cnt++;
}
else {
printf("0");
if (s[i] != '0')cnt++;
}
}else printf("%d", s[i] - '0');
}
printf("\n");
return 0;
}
C - Anadi and Domino
题解:
考虑给每一个点一个颜色,然后放Domino,求最多能放多少Domino
观察可以发现,如果
N
≤
6
N\leq6
N≤6,每个点都染成不同的颜色,可选的Domino有15个(减去形如1-1的Domino),而
N
=
6
N=6
N=6的情况下最多只有15条边,故直接输出边的数量即可
这里只需要考虑
N
=
7
N=7
N=7的情况
能放最多的情况一定是:6个点颜色各不相同,2个点颜色相同
这里我们枚举一对点
i
,
j
i,j
i,j使得他们颜色相同,不妨就记为颜色1,那么颜色1能连出去的边有6种,分别是
1-1, 1-2, 1-3, 1-4, 1-5, 1-6,而现在我们的1-1已经用了(连接
i
,
j
i,j
i,j这两个点的边),所以实际上两个点是共用这剩下的5条边,而每条边只能用一次,所以如果这两个点
i
,
j
i,j
i,j都与点
k
k
k连通的话,只能选其中一个点与其连通,也就是说原来算放了2个domino,现在只能算放1个,也就是损失掉了,现在算现在只需要枚举,找出最小的损失即可。
代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define sz sizeof
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAX = 1e4 + 10;
int N, M;
int grap[10][10];
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N >> M;
for (int i = 1; i <= M; i++) {
int u, v; cin >> u >> v;
grap[u][v] = grap[v][u] = 1;
}
if (N <= 6) cout << M;
else {
int minn = INF;//最小损失
for (int i = 1; i <= N; i++) {//枚举i,j
for (int j = i + 1; j <= N; j++) {
int cnt = 0;
for (int k = 1; k <= N; k++)//找出都连通的点
if (grap[i][k] && grap[j][k]) cnt++;
minn = min(minn, cnt);//更新最小损失
}
}
cout << M - minn;
}
cout << endl;
return 0;
}
D - Marcin and Training Camp
题解:
显然如果有至少两个人的
a
i
a_i
ai值相同,那么就不会出现这几个人歧视他人,所以值相同的人都可以加入集合
S
S
S,对于其他人
a
i
a_i
ai,只要能在集合
S
S
S找到至少一个无法去歧视的人,就是
a
i
a_i
ai这个人会的
a
j
a_j
aj都会
,即
(
a
i
∣
a
j
)
=
a
j
,
j
∈
S
(a_i|a_j)=a_j,j∈S
(ai∣aj)=aj,j∈S,那么就能加入集合。最后统计答案。
代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define sz sizeof
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAX = 7e3 + 10;
int N, tot;
ll s[MAX];
bool vis[MAX];
struct node {
ll a, b;
bool operator < (const node &num) const{
return a < num.a;
}
} point[MAX];
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N;
for (int i = 1; i <= N; i++) cin >> point[i].a;
for (int i = 1; i <= N; i++) cin >> point[i].b;
sort(point + 1, point + 1 + N);//排序一下方便后面加入a值相同的
ll ans = 0;
for (int i = 1; i <= N; i++) {
ll cnt = 1;
while (i + 1 <= N && point[i].a == point[i + 1].a) {//相同的a
vis[i] = 1;
ans += point[i].b;
cnt++;
i++;
}
if (cnt > 1) {
s[++tot] = point[i].a;//存入集合
vis[i] = 1;
ans += point[i].b;//加上答案
}
}
for (int i = 1; i <= N; i++)
if (!vis[i]) {//对于没有在集合里面的元素a_i
for (int j = 1; j <= tot; j++)
if ((point[i].a | s[j]) == s[j]) {//找到一个a_j,使得a_i会的a_j都会,那么就加入集合
ans += point[i].b;
break;
}
}
cout << ans << endl;
return 0;
}
E - Kamil and Making a Stream
题解:
这里直接dfs,每次一个一个算gcd然后统计是不行的(会T),得用
m
p
[
i
]
mp[i]
mp[i]存所有i和祖先节点gcd的值 及出现次数,这样可以大大减少计算次数,普通的记忆化搜索
代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define sz sizeof
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAX = 1e5 + 10;
const int mod = 1e9 + 7;
int N;
ll ans, val[MAX];
map<ll, int> mp[MAX];//mp[i]保存所有 i和祖先节点gcd值 和 出现次数
int tot, head[MAX];
ll gcd(ll a, ll b) {
if (a == 0 || b == 0)
return max(a, b);
ll c = a % b;
while (c) {
a = b;
b = c;
c = a % b;
}
return b;
}
struct {
int nxt, to;
} e[MAX << 1];
void add(int u, int v) {
e[++tot].nxt = head[u];
e[tot].to = v;
head[u] = tot;
}
void dfs(int u, int fa) {
for (auto &it : mp[fa])//当前点加上和父亲节点gcd
mp[u][gcd(val[u], it.first)] += it.second;
mp[u][val[u]]++;//加上自己和自己gcd
for (auto &it : mp[u])//统计答案
(ans += it.first * it.second % mod) %= mod;
for (int i = head[u]; i; i = e[i].nxt)//往下递归
if (e[i].to != fa) dfs(e[i].to, u);
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N;
for (int i = 1; i <= N; i++)
cin >> val[i];
for (int i = 1; i < N; i++) {
int u, v; cin >> u >> v;
add(u, v); add(v, u);
}
dfs(1, 0);
cout << ans << endl;
return 0;
}