AtCoder Beginner Contest 191

比赛链接

C Digital Graffiti

Description

题目链接

Solution

可以发现 (x,y)(x, y) 为顶点当且仅当 (Sx,y,Sx,y,Sx,y,Sx,y)(S_{x, y}, S_{x, y}, S_{x, y}, S_{x, y}) 中有一个或者三个为 #。于是二重循环枚举判断即可。

Code

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

using namespace std;

int main(){
int H, W;
cin >> H >> W;
vector<string> S(H);
for(auto& s : S) cin >> s;
int ans = 0;
for(int i = 0; i < H - 1; i++) for(int j = 0; j < W - 1; j++)
if(S[i][j] ^ S[i][j + 1] ^ S[i + 1][j] ^ S[i + 1][j + 1]) ans++;
cout << ans << endl;
}

D Circle Lattice Points

Description

题目链接

Solution

为防止浮点误差,将读入的小数乘以 10000 (注意不能乘 10000 后强制转化为整型)。然后枚举 xx,求出 yy 对应的取值范围,从而求出坐标为 xx 且在圆内的整数点的个数。求 y 的范围时涉及 sqrtsqrt 开根号,也会产生误差,考虑加一个偏移区间,求出 yy 的正确上下界。

也有直接求的做法 Submission;

Code

Circle Lattice Points
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
62
63
64
65
66
67
68
69
70
71
72
#include <bits/stdc++.h>

#define debug(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

const int MAXN = 2E5 + 5;
const int MOD = 1E9 + 7;
int n, m;

LL get(LL val) {
LL tmp = val % 10000;
if (val >= 0)
return val - tmp;
else
return val - tmp - (tmp == 0 ? 0 : 10000);
} //返回小于等于的第一个能模10000的数

void solve(int testNum) {
// type your code here
string aa, bb, rr;
LL a = 0, b = 0, r = 0;
cin >> aa >> bb >> rr;
int cnta = 4, cntb = 4, cntr = 4;
bool taga = 0, tagb = 0, tagr = 0;
for (int i = 0; i < aa.size(); i++) {
if (taga) cnta--;
if (aa[i] != '.')
a = a * 10 + aa[i] - '0';
else
taga = 1;
}
while (cnta) a *= 10, cnta--;

for (int i = 0; i < bb.size(); i++) {
if (tagb) cntb--;
if (bb[i] != '.')
b = b * 10 + bb[i] - '0';
else
tagb = 1;
}
while (cntb) b *= 10, cntb--;

for (int i = 0; i < rr.size(); i++) {
if (tagr) cntr--;
if (rr[i] != '.')
r = r * 10 + rr[i] - '0';
else
tagr = 1;
}
while (cntr) r *= 10, cntr--;
LL ans = 0;
for (LL y = get(b - r); y <= get(b + r); y += 10000) {
LL res = r * r - (y - b) * (y - b);
if (res > 0) {
LL tmp = sqrt(res);
LL k1 = get(-tmp + a) - 100000, k2 = get(tmp + a) + 1000000;
while ((k1 - a) * (k1 - a) > res) k1+=10000;
while ((k2 - a) * (k2 - a) > res) k2-=10000;
ans += (k2 - k1) / 10000 + 1;
} else if (res == 0 && a % 10000 == 0)
ans++;
}
cout << ans;
}

signed main() {
int testCase = 1;
for (int i = 1; i <= testCase; i++) solve(i);
return 0;
}

E Come Back Quickly

Description

题目链接

Solution

  • 询问在有向图中从起点出发回到起点的最短回路。

  • 先求出单源最短路,由于 diststartdist_start 初始值为0,故需枚举每个点 ii,答案为 disti+wi,startdist_i + w_{i, start} 的最小值。

Code

Come Back Quickly
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
#include <bits/stdc++.h>

using namespace std;

#define debug(x) cerr << #x << " = " << x << endl
#define boost ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

constexpr int MAXN = 2002, MOD = 1e9 + 7;

int n, m;
vector<pair<int, int>> g[MAXN];
array<int, MAXN> dis, inq, self;

void spfa(int st) {
for (int i = 1; i <= n; i++) dis[i] = 1e9, inq[i] = false;
queue<int> q;
q.push(st), inq[st] = true;
dis[st] = 0;
while (!q.empty()) {
int cur = q.front();
q.pop();
inq[cur] = false;
for (auto& e : g[cur]) {
int to = e.first, w = e.second;
if (dis[to] > dis[cur] + w) {
dis[to] = dis[cur] + w;
if (!inq[to]) {
q.push(to);
inq[to] = true;
}
}
}
}
int ans = 1e9;
for (int i = 1; i <= n; i++) {
for (auto & e : g[i]) {
if (e.first == st) {
ans = min(ans, dis[i] + e.second);
}
}
}
if (ans != 1e9) cout << ans << "\n";
else cout << "-1\n";
}


signed main() {
boost;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
}
for (int i = 1; i <= n; i++) spfa(i);
return 0;
}

F GCD or MIN

Description

题目链接

Solution

  • 经过一系列操作后结果一定小于等于 min(Ai)min(A_i)

  • 小于 min(Ai)min(A_i) 的数是通过 AA 数组中的一些数取 gcdgcd 再取最小值得到,即是一些数的约数。于是可以 O(nmax(sqrt(Ai)))O(n * max(sqrt(A_i))) 求出小于 min(Ai)min(A_i) 的约数,然后求出其在 AA 数组中的倍数,判断它们的 gcdgcd 是否为该约数。

  • 由于 nn 个数的不同约数个数大概为 nlog(n)n * log(n),故总时间复杂度为 O(nmax(sqrt(Ai))+n2log(n))O(n * max(sqrt(A_i)) + n^2 * log(n))

Code

GCD or MIN
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
#include <bits/stdc++.h>

using namespace std;

#define boost ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

constexpr int MAXN = 1e5 + 5, MOD = 1e9 + 7;

int n, mn;
array<int, MAXN> a;
vector<int> divs;

int main() {
boost;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
mn = *min_element(a.begin() + 1, a.begin() + n + 1);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sqrt(a[i]); j++) {
if (a[i] % j == 0) divs.push_back(j), divs.push_back(a[i] / j);
}
}
sort(divs.begin(), divs.end());
auto ed = unique(divs.begin(), divs.end());
int ans = 0;
for (auto it = divs.begin(); it != ed; ++it) {
if (*it >= mn) continue;
vector<int> vec;
for (int i = 1; i <= n; i++) if (a[i] % (*it) == 0) vec.push_back(a[i]);
if (vec.size() <= 1) continue;
int gcd = vec.front();
for (int i = 1; i < vec.size(); i++)
gcd = __gcd(gcd, vec[i]);
if (gcd == *it) ans++;
}
cout << ans + 1 << "\n";
return 0;
}