[R7A] K 的倍数
求区间 [L, R] 中 K 的倍数的个数。
法 1: 暴力枚举
因为数据集不大,所以可以直接遍历区间 [L, R]。
#include <bits/stdc++.h>
using namespace std;
int main() {
int l, r, k, ans = 0;
cin >> l >> r >> k;
for (int i = l; i <= r; i++) {
if (i % k == 0) {
ans++;
}
}
cout << ans << endl;
return 0;
}
法 2: 前缀和思想
因为区间 [1, R] 中 K 的倍数的个数为: R / K
所以区间 [L, R] 的个数 = 区间 [1, R] 的个数 - 区间 [1, L - 1] 的个数。
#include <bits/stdc++.h>
using namespace std;
int main() {
int l, r, k, ans = 0;
cin >> l >> r >> k;
ans = r / k - (l - 1) / k;
cout << ans << endl;
return 0;
}
[R7B] 炸弹
给定一个由
@(表示炸弹)和.组成的 n * m 的字符矩阵,位于 (i, j) 的炸弹会炸到满足 ∣x - i∣+∣y - j∣≤ 3 的任意格子 (x, y)。
求每个格子会被多少个炸弹炸到。数据范围:
准备工作:
const int N = 1010, M = 1010;
int n, m, ans[N][M]; // 记录每个格子会被多少个炸弹炸到
// 判断格子坐标是否合法
bool in_range(int x, int y) {
return (x >= 0 && x <= n && y >= 0 && y <= m);
}
// 通过坐标 (i, j) 找到满足 ∣x - i∣ + ∣y - j∣ ≤ 3 的合法格子 (x, y)
for (int x = i - 3; x <= i + 3; x++) {
for (int y = j - 3; y <= j + 3; y++) {
if ((abs(x - i) + abs(y - j) <= 3) && in_range(x, y)) {
...
}
}
}
方法 1: 通过炸弹位置,找到被它炸到的格子
void solve(int i, int j) {
if (s[i][j] != '@') {
return;
}
for (int x = i - 3; x <= i + 3; x++) {
for (int y = j - 3; y <= j + 3; y++) {
if ((abs(x - i) + abs(y - j) <= 3) && in_range(x, y)) {
ans[x][y]++;
}
}
}
}
方法 2: 对于每个格子,找到它附近的炸弹
void solve(int i, int j) {
for (int x = i - 3; x <= i + 3; x++) {
for (int y = j - 3; y <= j + 3; y++) {
if ((abs(x - i) + abs(y - j) <= 3) && in_range(x, y) && s[x][y] == '@') {
ans[i][j]++;
}
}
}
}
完整代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 1010;
char s[N][M];
int n, m, ans[N][M];
bool in_range(int x, int y) {
return (x >= 0 && x <= n && y >= 0 && y <= m);
}
void solve(int i, int j) {
if (s[i][j] != '@') {
return;
}
for (int x = i - 3; x <= i + 3; x++) {
for (int y = j - 3; y <= j + 3; y++) {
if ((abs(x - i) + abs(y - j) <= 3) && in_range(x, y)) {
ans[x][y]++;
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
scanf("%s", s[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
solve(i, j);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d ", ans[i][j]);
}
printf("\n");
}
return 0;
}
[R7C] 二维 gcd 和
求 mod 998244353
对于 50% 的数据,
对于 100% 的数据,
gcd: 最大公约数
int gcd(int x, int y) {
if (y == 0) {
return x;
}
return gcd(y, x % y);
}
50 分的做法:
void solve() {
for (int i = 1; i <= n; i++) {
int di = gcd(i, n);
for (int j = 1; j <= m; j++) {
int dj = gcd(j, m);
ans = (ans + 1LL * di * dj) % P;
}
}
}
100 分的做法:
提取公因数:
因此可以先把 计算出来,就可以将原来的两层循环简化成一层循环。
void solve() {
int dj = 0;
for (int j = 1; j <= m; j++) {
dj = (gcd(j, m) + dj) % P;
}
for (int i = 1; i <= n; i++) {
int di = gcd(i, n);
ans = (ans + 1LL * di * dj) % P;
}
}
完整代码
#include <bits/stdc++.h>
using namespace std;
const int P = 998244353;
int n, m;
long long ans = 0;
int gcd(int x, int y) {
if (y == 0) {
return x;
}
return gcd(y, x % y);
}
void solve() {
int dj = 0;
for (int j = 1; j <= m; j++) {
dj = (gcd(j, m) + dj) % P;
}
for (int i = 1; i <= n; i++) {
int di = gcd(i, n);
ans = (ans + 1LL * di * dj) % P;
}
}
int main() {
cin >> n >> m;
solve();
cout << ans << endl;
return 0;
}