A – 游戏
我大概乱搞一下:从最外围向内操作,计算操作次数再取模然后对应姓名即可。我不太了解为什么就过了。
// A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e3 + 200;
char mp[MAX_N][MAX_N];
int n, m, T, delta[MAX_N][MAX_N], now[MAX_N][MAX_N], matrix[MAX_N][MAX_N];
int main()
{
scanf("%d", &T);
while (T--)
{
memset(delta, 0, sizeof(delta)), memset(now, 0, sizeof(now));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%s", mp[i] + 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (mp[i][j] == 'R')
matrix[i][j] = 1;
else if (mp[i][j] == 'G')
matrix[i][j] = 2;
else
matrix[i][j] = 0;
int cnt = 0;
for (int i = n; i >= 1; i--)
{
delta[i][m + 1] += delta[i + 1][m + 1];
for (int j = m; j >= 1; j--)
{
delta[i][j] += delta[i + 1][j];
now[i][j] = now[i][j + 1] + delta[i][j + 1];
int curt = (matrix[i][j] + now[i][j]) % 3;
cnt += (3 - curt) % 3;
now[i][j] += (3 - curt) % 3, delta[i][j + 1] += (3 - curt) % 3;
}
}
printf("%s\n", cnt % 3 == 2 ? "dreagonm" : (cnt % 3 == 1 ? "fengxunling" : "BLUESKY007"));
}
return 0;
}
// A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e3 + 200;
char mp[MAX_N][MAX_N];
int n, m, T, delta[MAX_N][MAX_N], now[MAX_N][MAX_N], matrix[MAX_N][MAX_N];
int main()
{
scanf("%d", &T);
while (T--)
{
memset(delta, 0, sizeof(delta)), memset(now, 0, sizeof(now));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%s", mp[i] + 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (mp[i][j] == 'R')
matrix[i][j] = 1;
else if (mp[i][j] == 'G')
matrix[i][j] = 2;
else
matrix[i][j] = 0;
int cnt = 0;
for (int i = n; i >= 1; i--)
{
delta[i][m + 1] += delta[i + 1][m + 1];
for (int j = m; j >= 1; j--)
{
delta[i][j] += delta[i + 1][j];
now[i][j] = now[i][j + 1] + delta[i][j + 1];
int curt = (matrix[i][j] + now[i][j]) % 3;
cnt += (3 - curt) % 3;
now[i][j] += (3 - curt) % 3, delta[i][j + 1] += (3 - curt) % 3;
}
}
printf("%s\n", cnt % 3 == 2 ? "dreagonm" : (cnt % 3 == 1 ? "fengxunling" : "BLUESKY007"));
}
return 0;
}
// A.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e3 + 200; char mp[MAX_N][MAX_N]; int n, m, T, delta[MAX_N][MAX_N], now[MAX_N][MAX_N], matrix[MAX_N][MAX_N]; int main() { scanf("%d", &T); while (T--) { memset(delta, 0, sizeof(delta)), memset(now, 0, sizeof(now)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (mp[i][j] == 'R') matrix[i][j] = 1; else if (mp[i][j] == 'G') matrix[i][j] = 2; else matrix[i][j] = 0; int cnt = 0; for (int i = n; i >= 1; i--) { delta[i][m + 1] += delta[i + 1][m + 1]; for (int j = m; j >= 1; j--) { delta[i][j] += delta[i + 1][j]; now[i][j] = now[i][j + 1] + delta[i][j + 1]; int curt = (matrix[i][j] + now[i][j]) % 3; cnt += (3 - curt) % 3; now[i][j] += (3 - curt) % 3, delta[i][j + 1] += (3 - curt) % 3; } } printf("%s\n", cnt % 3 == 2 ? "dreagonm" : (cnt % 3 == 1 ? "fengxunling" : "BLUESKY007")); } return 0; }
B – 水果蛋糕
我先打了个表,把\(n \in [3, 6]\)的都打了一遍,然后发现规律;可惜我用了非常丑的写法,打表打废掉了。最后到手只有 20 分。正解如下:
// B.cpp
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll n, m;
scanf("%lld%lld", &n, &m);
if (n < m)
swap(n, m);
if (m <= 2)
printf("%lld", n * m);
else if (m == 3)
printf("%lld", n + 6 * (n / 6) + 2 * min(n % 6, 3LL));
else if (m == 4)
{
if (n % 6 == 0)
printf("%lld", 2 * n);
else if (n % 6 == 1 || n % 6 == 2)
printf("%lld", 12 * (n / 6) + 4 * (n % 6));
else if (n % 6 == 3 || n % 6 == 4)
printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * ((n % 6) - 2));
else
printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * 2);
}
else
printf("%lld", (n * m + 1) / 2);
return 0;
}
// B.cpp
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll n, m;
scanf("%lld%lld", &n, &m);
if (n < m)
swap(n, m);
if (m <= 2)
printf("%lld", n * m);
else if (m == 3)
printf("%lld", n + 6 * (n / 6) + 2 * min(n % 6, 3LL));
else if (m == 4)
{
if (n % 6 == 0)
printf("%lld", 2 * n);
else if (n % 6 == 1 || n % 6 == 2)
printf("%lld", 12 * (n / 6) + 4 * (n % 6));
else if (n % 6 == 3 || n % 6 == 4)
printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * ((n % 6) - 2));
else
printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * 2);
}
else
printf("%lld", (n * m + 1) / 2);
return 0;
}
// B.cpp #include <bits/stdc++.h> typedef long long ll; using namespace std; int main() { ll n, m; scanf("%lld%lld", &n, &m); if (n < m) swap(n, m); if (m <= 2) printf("%lld", n * m); else if (m == 3) printf("%lld", n + 6 * (n / 6) + 2 * min(n % 6, 3LL)); else if (m == 4) { if (n % 6 == 0) printf("%lld", 2 * n); else if (n % 6 == 1 || n % 6 == 2) printf("%lld", 12 * (n / 6) + 4 * (n % 6)); else if (n % 6 == 3 || n % 6 == 4) printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * ((n % 6) - 2)); else printf("%lld", 12 * (n / 6) + 4 * 2 + 2 * 2); } else printf("%lld", (n * m + 1) / 2); return 0; }
C – 好朋友
典型的正难则反系列,刚开始觉得这题比较好做,但是数位 DP 还是不太会处理导致全部炸裂(明天要去做做板子了)。设置状态\(dp[i][j]\)计算长度为\(i\)的、有\(j\)个零的数的个数。防止出现七就行了。具体处理见正解代码:
// C.cpp
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll predigits[20], dp[20][4], T, digits[20];
ll solve(ll pos)
{
if (pos < 1000)
return 0;
int tot = 0, x = 0;
for (; pos; pos /= 10)
digits[tot++] = pos % 10;
reverse(digits, digits + tot);
memset(dp, 0, sizeof(dp));
dp[1][0] = digits[0] - 1;
for (int i = 1; i < tot; i++)
{
dp[i + 1][0] = dp[i][0] * 9, dp[i + 1][1] = dp[i][0] + dp[i][1] * 9;
dp[i + 1][2] = dp[i][1] + dp[i][2] * 9, dp[i + 1][3] = dp[i][2] + dp[i][3] * 10;
dp[i + 1][x] += digits[i] - 1;
dp[i + 1][x + ((x < 2 && digits[i]) || (x == 2 && digits[i] > 7))]++;
if (((x < 2 && !digits[i]) || (x == 2 && digits[i] == 7)))
x++;
}
return predigits[tot - 1] + dp[tot][3];
}
int main()
{
for (ll i = 0, val = 1; i <= 18; i++, val *= 10)
predigits[i] = solve(val - 1);
ll ans = 0;
scanf("%lld", &T);
while (T--)
{
ll lft, rig;
scanf("%lld%lld", &lft, &rig);
ans ^= (solve(rig + 1) - solve(lft));
}
printf("%lld", ans);
return 0;
}
// C.cpp
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll predigits[20], dp[20][4], T, digits[20];
ll solve(ll pos)
{
if (pos < 1000)
return 0;
int tot = 0, x = 0;
for (; pos; pos /= 10)
digits[tot++] = pos % 10;
reverse(digits, digits + tot);
memset(dp, 0, sizeof(dp));
dp[1][0] = digits[0] - 1;
for (int i = 1; i < tot; i++)
{
dp[i + 1][0] = dp[i][0] * 9, dp[i + 1][1] = dp[i][0] + dp[i][1] * 9;
dp[i + 1][2] = dp[i][1] + dp[i][2] * 9, dp[i + 1][3] = dp[i][2] + dp[i][3] * 10;
dp[i + 1][x] += digits[i] - 1;
dp[i + 1][x + ((x < 2 && digits[i]) || (x == 2 && digits[i] > 7))]++;
if (((x < 2 && !digits[i]) || (x == 2 && digits[i] == 7)))
x++;
}
return predigits[tot - 1] + dp[tot][3];
}
int main()
{
for (ll i = 0, val = 1; i <= 18; i++, val *= 10)
predigits[i] = solve(val - 1);
ll ans = 0;
scanf("%lld", &T);
while (T--)
{
ll lft, rig;
scanf("%lld%lld", &lft, &rig);
ans ^= (solve(rig + 1) - solve(lft));
}
printf("%lld", ans);
return 0;
}
// C.cpp #include <bits/stdc++.h> typedef long long ll; using namespace std; ll predigits[20], dp[20][4], T, digits[20]; ll solve(ll pos) { if (pos < 1000) return 0; int tot = 0, x = 0; for (; pos; pos /= 10) digits[tot++] = pos % 10; reverse(digits, digits + tot); memset(dp, 0, sizeof(dp)); dp[1][0] = digits[0] - 1; for (int i = 1; i < tot; i++) { dp[i + 1][0] = dp[i][0] * 9, dp[i + 1][1] = dp[i][0] + dp[i][1] * 9; dp[i + 1][2] = dp[i][1] + dp[i][2] * 9, dp[i + 1][3] = dp[i][2] + dp[i][3] * 10; dp[i + 1][x] += digits[i] - 1; dp[i + 1][x + ((x < 2 && digits[i]) || (x == 2 && digits[i] > 7))]++; if (((x < 2 && !digits[i]) || (x == 2 && digits[i] == 7))) x++; } return predigits[tot - 1] + dp[tot][3]; } int main() { for (ll i = 0, val = 1; i <= 18; i++, val *= 10) predigits[i] = solve(val - 1); ll ans = 0; scanf("%lld", &T); while (T--) { ll lft, rig; scanf("%lld%lld", &lft, &rig); ans ^= (solve(rig + 1) - solve(lft)); } printf("%lld", ans); return 0; }
我认为这几场 OI 周赛的题质量不高。