惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
B
Blog
博客园 - 三生石上(FineUI控件)
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Vercel News
Vercel News
量子位
A
About on SuperTechFans
博客园 - 聂微东
WordPress大学
WordPress大学
D
DataBreaches.Net
The Cloudflare Blog
M
MIT News - Artificial intelligence
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
雷峰网
雷峰网
C
Check Point Blog
S
SegmentFault 最新的问题
U
Unit 42
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research

Shiroha白羽的博客

Golang 踩坑 —— interface 为参数的时候传 nil 指针 Codeforces Round 925 (Div. 3) Codeforces Round 924 (Div. 2) Codeforces Round 923 (Div. 3) Codeforces Round 922 (Div. 2) Codeforces Round 921 (Div. 2) Educational Codeforces Round 161 (Rated for Div. 2) Codeforces Round 920 (Div. 3) Codeforces Round 919 (Div. 2) Hello 2024 Good Bye 2023 Codeforces Round 918 (Div. 4) 个人备份的常用 macOS 清理命令 Codeforces Round 917 (Div. 2) Pinely Round 3 (Div. 1 + Div. 2) Educational Codeforces Round 160 (Rated for Div. 2) Codeforces Round 915 (Div. 2) Codeforces Round 914 (Div. 2) Codeforces Round 913 (Div. 3) Educational Codeforces Round 159 (Rated for Div. 2) Codeforces Round 912 (Div. 2) Codeforces Round 911 (Div. 2) CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!) Educational Codeforces Round 158 (Rated for Div. 2) Codeforces Round 910 (Div. 2) Codeforces Round 909 (Div. 3) Codeforces Round 908 (Div. 2) Educational Codeforces Round 157 (Rated for Div. 2) C++自定义的字面量 Codeforces Round 907 (Div. 2)
Codeforces Round#697 (Div. 3)
Shiroha · 2021-01-26 · via Shiroha白羽的博客

自南京区域赛结束之后就一直在准备期末考试,直到最近结束考试之后开始了复建的生活,这场 Div3 除了 D 题因为爆了 int 然后卡了,G题真的没在比赛期间想出来,其他题目都是非常顺利的解决掉了,且只用了一个小时

A. Odd Divisor

题目大意

给你一个整数,请问它是否存在一个不为 1 的奇因子

题解

因为除 1 以外的所有奇因子都可以分解出至少一个奇质因子,那么只需要找到那些不包含奇质因子的数进行排查就行。而不包含奇质因子的数字很明显就是所有的 2 的幂次,所以打表就可以了。注意别忘记范围超过了 int

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>

using namespace std;

#define int long long

int main() {
set<int> err;
int cur = 2;
for (int i = 0; i < 62; ++i) {
err.insert(cur);
cur <<= 1;
}
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int tmp;
cin >> tmp;
cout << (err.count(tmp) ? "NO" : "YES") << endl;
}
}

B. New Year’s Number

题目大意

给你一个数,请问它是不是 n 个 2020 和 m 个 2021 相加得到的

题解

把 2021 看成 2020 + 1,那么就变成了 (n + m) 个 2020 和 m 个 1 相加得到,由于 n 肯定是自然数,则只要满足这个数除以 2020 的商(也就是 n + m 部分)大于等于余数(也就是 m)即可

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <bits/stdc++.h>

using namespace std;

int main() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int tmp;
cin >> tmp;
cout << (tmp / 2020 >= tmp % 2020 ? "YES" : "NO") << endl;
}
}

C. Ball in Berland

题目大意

有两组人,分别为 a 和 b ,有 k 对组合,每对组合都是从 a 中选出一个,从 b 中选出一个。你现在需要选出两对组合,使得这两对组合不会发生冲突,即不会出现 a 中的人同时参与了这两个组合或者 b 中的人同时参与了这两个组合或者两者都同时参与

题解

可以用类似容斥的办法解决。因为保证了每一对组合都不同,所以当我选出一对的时候,那么还有 k - cnt[a] - cnt[b] + 1 对我可以选,其中的 cnt 为这个人参与的组合数量。只需要遍历所有的组合,然后对于每对组合进行求解即可

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>

using namespace std;

int main() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int a, b, k;
cin >> a >> b >> k;
vector<int> ca(a + 1), cb(b + 1);
vector<pair<int, int>> p(k);
for (int i = 0; i < k; ++i) {
int u;
cin >> u;
p[i].first = u;
ca[u]++;
}
for (int i = 0; i < k; ++i) {
int u;
cin >> u;
p[i].second = u;
cb[u]++;
}
long long ans = 0;
for (int i = 0; i < k; ++i) ans += k - ca[p[i].first] - cb[p[i].second] + 1;
cout << ans / 2 << endl;
}
}

D. Cleaning the Phone

大致题意

有一组物品,他们有各自的代价和价值,其中代价只有 1 或者 2 两种,请问如何选择物品,使得代价尽可能小的情况下满足所需要的价值

题解

直接考虑枚举,比如枚举选择了 x 件代价为 1 的物品,求出这时候至少需要多少件代价为 2 的物品,然后枚举所有情况,输出最小的情况即可。

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>

using namespace std;

#define int long long

int main() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, m;
cin >> n >> m;
vector<int> mem(n);
vector<int> data[2];
for (int i = 0; i < n; ++i) cin >> mem[i];
for (int i = 0; i < n; ++i) {
int op;
cin >> op;
data[op - 1].push_back(mem[i]);
}
sort(data[0].begin(), data[0].end(), greater<int>());
sort(data[1].begin(), data[1].end(), greater<int>());
int ans = INT_MAX;
for (int i = 1; i < data[0].size(); ++i) data[0][i] += data[0][i - 1];
for (int i = 1; i < data[1].size(); ++i) data[1][i] += data[1][i - 1];

auto iter = lower_bound(data[1].begin(), data[1].end(), m);
if (iter != data[1].end()) ans = min(ans, (int) (iter - data[1].begin() + 1) * 2);

iter = lower_bound(data[0].begin(), data[0].end(), m);
if (iter != data[0].end()) ans = min(ans, (int) ((iter - data[0].begin() + 1)));

for (int i = 0; i < data[0].size(); ++i) {
iter = lower_bound(data[1].begin(), data[1].end(), m - data[0][i]);
if (iter != data[1].end()) ans = min(ans, (int) ((iter - data[1].begin() + 1) * 2 + i + 1));
}

for (int i = 0; i < data[1].size(); ++i) {
iter = lower_bound(data[0].begin(), data[0].end(), m - data[1][i]);
if (iter != data[0].end()) ans = min(ans, (int) ((iter - data[0].begin() + 1) + 2 * (i + 1)));
}
cout << (ans == INT_MAX ? -1 : ans) << endl;
}
}

E. Advertising Agency

大致题意

给你一组数据,要求你从中取出 k 个数据,使得这 k 个数据的之和最大,问有几种取法

题解

首先取最大必然只能从大到小取,直到取满 k 个。但是在取最后几个相同的值的时候,由于有多个选择,则可以产生多个方案。而这个方案数量很明显即为组合数。

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1100;

ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}

ll fac[N], ifac[N];

void init(int siz) {
fac[0] = 1;
for (int i = 1; i <= siz; i++)
fac[i] = i * fac[i - 1] % mod;
ifac[siz] = qpow(fac[siz], mod - 2);
for (int i = siz; i >= 1; i--) ifac[i - 1] = ifac[i] * i % mod;
}

ll C(ll n, ll m) {
if (m == 0 || n == m) return 1;
if (m > n) return 0;
if (m == 1) return n;
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}

int main() {
init(1050);
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, k;
cin >> n >> k;
map<int, int> mp;
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
mp[tmp]++;
}

auto iter = mp.rbegin();
while (iter != mp.rend()) {
if (k > iter->second) {
k -= iter->second;
iter++;
} else {
cout << C(iter->second, k) << endl;
break;
}
}
}
}

F. Unusual Matrix

大致题意

给你两个 01 矩阵,问能否通过下面两个方式将第一个矩阵转为和第二个矩阵一样

  • 将一行的值翻转
  • 将一列的值翻转

题解

由于是翻转相同,那么首先直接对这两个矩阵做异或,可以得到一个矩阵,接下来只需要把这个矩阵给转为只有 0 或者只有 1 的矩阵即可

这时候其实可以模拟,假定这行第一个值为 1 则翻转,否者不翻转,然后最后判定是否为纯 0 矩阵

但是这样太麻烦了,其实可以直接判断相邻两行之间是否相同或者相异,即任意两行或者两列的异或结果全为 0 或者 全为 1 则可以,否则不可以

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>

using namespace std;

int main() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<string> data1(n), data2(n);
for (int i = 0; i < n; ++i) cin >> data1[i];
for (int i = 0; i < n; ++i) cin >> data2[i];
for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) data1[i][j] = (data1[i][j] - '0') ^ (data2[i][j] - '0');
bool flag = true;
for (int i = 1; i < n; ++i) {
char tmp = data1[i][0] ^ data1[i - 1][0];
for (int j = 0; j < n; ++j) {
if ((data1[i][j] ^ data1[i - 1][j]) != tmp) {
flag = false;
break;
}
}
if (!flag) break;
}
cout << (flag ? "YES" : "NO") << endl;
}
}

G. Strange Beauty

大致题意

给你一组数列,请问至少需要删除几个数字,使得整个数列的任意两个值满足大数取模小数为 0

题解

利用素数筛的方式来 dp 求算最多能有多少个值能满足此条件,相减就能得到答案

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <bits/stdc++.h>

using namespace std;

int main() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<int> cnt(2e5 + 1), dp(2e5 + 1);
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
cnt[tmp]++;
}
int ans = 0;
for (int i = 1; i <= 2e5; ++i) {
dp[i] += cnt[i];
for (int j = i + i; j <= 2e5; j += i) dp[j] = max(dp[j], dp[i]);
ans = max(ans, dp[i]);
}
cout << n - ans << endl;
}
}