// A.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, A, B;
scanf("%d%d%d%d", &n, &m, &B, &A);
for (int i = 1; i <= n; i++, puts(""))
for (int j = 1; j <= m; j++)
if ((i <= A) ^ (j <= B))
printf("1");
else
printf("0");
return 0;
}
// A.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, A, B;
scanf("%d%d%d%d", &n, &m, &B, &A);
for (int i = 1; i <= n; i++, puts(""))
for (int j = 1; j <= m; j++)
if ((i <= A) ^ (j <= B))
printf("1");
else
printf("0");
return 0;
}
B – Sorting a Segment
这个题姑且有点意思。首先答案上限是 \(n – k + 1\),然后我们可以思考两个区间的排序效果是否相同。有两种情况:
第一种情况是两个区间并不相交,那么排序效果相同的充要条件就是这两个区间都是单调不降的。这个东西用 ST 表可以轻松维护。
可以观察出一个结论,如果两个区间 \([i, i + k – 1], [j, j + k – 1], i < j\) 满足效果相同,那么 \([i, i + k – 1]\) 与 \([x, x + k – 1], x \in [i, j]\) 是效果相同的。知道这个结论之后可以直接 \(\Theta(n)\) 扫。
当然还要注意整个区间都是单调不降的情况。
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// B.cpp
#include <bits/stdc++.h>
usingnamespace std;
constint MAX_N = 2e5 + 200;
int n, k, pi[MAX_N], max_val[20][MAX_N], min_val[20][MAX_N], log2_[MAX_N];
p1 = (0LL + p1 + 1LL * bi[i] * i % mod) % mod, p2 = (0LL + p2 + 1LL * bi[i] * i % mod * i % mod) % mod;
int pans = (0LL + 1LL * p1 * p1 % mod + mod - p2) % mod * inv2 % mod;
ans = (0LL + ans + 1LL * pans * ci[d] % mod) % mod;
}
printf("%d\n", ans);
return 0;
}
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6 + 200, mod = 998244353;
int n, upper, ai[MAX_N], bi[MAX_N], ci[MAX_N];
int fpow(int bas, int tim)
{
int ret = 1;
while (tim)
{
if (tim & 1)
ret = 1LL * ret * bas % mod;
bas = 1LL * bas * bas % mod;
tim >>= 1;
}
return ret;
}
const int inv2 = fpow(2, mod - 2);
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]), bi[ai[i]]++;
upper = *max_element(ai + 1, ai + 1 + n);
for (int i = 1; i <= upper; i++)
ci[i] = fpow(i, mod - 2);
for (int i = 1; i <= upper; i++)
for (int j = (i << 1); j <= upper; j += i)
ci[j] = (0LL + ci[j] + mod - ci[i]) % mod;
int ans = 0;
for (int d = 1; d <= upper; d++)
{
int p1 = 0, p2 = 0;
for (int i = d; i <= upper; i += d)
p1 = (0LL + p1 + 1LL * bi[i] * i % mod) % mod, p2 = (0LL + p2 + 1LL * bi[i] * i % mod * i % mod) % mod;
int pans = (0LL + 1LL * p1 * p1 % mod + mod - p2) % mod * inv2 % mod;
ans = (0LL + ans + 1LL * pans * ci[d] % mod) % mod;
}
printf("%d\n", ans);
return 0;
}
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6 + 200, mod = 998244353;
int n, upper, ai[MAX_N], bi[MAX_N], ci[MAX_N];
int fpow(int bas, int tim)
{
int ret = 1;
while (tim)
{
if (tim & 1)
ret = 1LL * ret * bas % mod;
bas = 1LL * bas * bas % mod;
tim >>= 1;
}
return ret;
}
const int inv2 = fpow(2, mod - 2);
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]), bi[ai[i]]++;
upper = *max_element(ai + 1, ai + 1 + n);
for (int i = 1; i <= upper; i++)
ci[i] = fpow(i, mod - 2);
for (int i = 1; i <= upper; i++)
for (int j = (i << 1); j <= upper; j += i)
ci[j] = (0LL + ci[j] + mod - ci[i]) % mod;
int ans = 0;
for (int d = 1; d <= upper; d++)
{
int p1 = 0, p2 = 0;
for (int i = d; i <= upper; i += d)
p1 = (0LL + p1 + 1LL * bi[i] * i % mod) % mod, p2 = (0LL + p2 + 1LL * bi[i] * i % mod * i % mod) % mod;
int pans = (0LL + 1LL * p1 * p1 % mod + mod - p2) % mod * inv2 % mod;
ans = (0LL + ans + 1LL * pans * ci[d] % mod) % mod;
}
printf("%d\n", ans);
return 0;
}
D – Unique Path
这个题可以大概知道一个思路:首先这个形态是一个若干双连通分量组成的树,那么在可以乱搞的情况下,判断 YES 和 NO 的唯一标准就是 \(m\) 是否在制定的范围之内。我们需要算边的下限和上限。当然,非法的情况需要我们提前判掉。
ans = (0LL + ans + 1LL * fac[idx] * acc % mod * dp[b][s][idx] % mod) % mod;
}
ans = 1LL * ans * sa % mod, printf("%d\n", ans);
return 0;
}
// E.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 440, mod = 998244353;
int n, ai[MAX_N], bi[MAX_N], sa, sb, inv[MAX_N], fac[MAX_N], dp[2][MAX_N][MAX_N];
int fpow(int bas, int tim)
{
int ret = 1;
while (tim)
{
if (tim & 1)
ret = 1LL * ret * bas % mod;
bas = 1LL * bas * bas % mod;
tim >>= 1;
}
return ret;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &ai[i], &bi[i]), sa += ai[i], sb += bi[i];
inv[0] = inv[1] = 1;
for (int i = 2; i < MAX_N; i++)
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
for (int i = fac[0] = 1; i < MAX_N; i++)
fac[i] = 1LL * fac[i - 1] * i % mod;
for (int i = 1; i < MAX_N; i++)
inv[i] = 1LL * inv[i] * inv[i - 1] %
int b = 0;
dp[0][0][0] = mod - 1;
for (int i = 1; i <= n; i++)
{
b ^= 1;
for (int s = 0; s <= sa; s++)
for (int c = 0; c <= sb; c++)
{
dp[b][s][c] = dp[!b][s][c];
if (s < ai[i])
continue;
for (int idx = 0, acc = 1; idx < bi[i] && idx <= c; idx++, acc = 1LL * acc * ai[i] % mod)
dp[b][s][c] = (0LL + dp[b][s][c] + mod - 1LL * acc * inv[idx] % mod * dp[!b][s - ai[i]][c - idx] % mod) % mod;
}
}
int ans = 0;
for (int s = 0; s <= sa; s++)
{
int unit = fpow(s, mod - 2);
for (int idx = 0, acc = unit; idx <= sb; idx++, acc = 1LL * acc * unit % mod)
ans = (0LL + ans + 1LL * fac[idx] * acc % mod * dp[b][s][idx] % mod) % mod;
}
ans = 1LL * ans * sa % mod, printf("%d\n", ans);
return 0;
}
// E.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 440, mod = 998244353;
int n, ai[MAX_N], bi[MAX_N], sa, sb, inv[MAX_N], fac[MAX_N], dp[2][MAX_N][MAX_N];
int fpow(int bas, int tim)
{
int ret = 1;
while (tim)
{
if (tim & 1)
ret = 1LL * ret * bas % mod;
bas = 1LL * bas * bas % mod;
tim >>= 1;
}
return ret;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &ai[i], &bi[i]), sa += ai[i], sb += bi[i];
inv[0] = inv[1] = 1;
for (int i = 2; i < MAX_N; i++)
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
for (int i = fac[0] = 1; i < MAX_N; i++)
fac[i] = 1LL * fac[i - 1] * i % mod;
for (int i = 1; i < MAX_N; i++)
inv[i] = 1LL * inv[i] * inv[i - 1] %
int b = 0;
dp[0][0][0] = mod - 1;
for (int i = 1; i <= n; i++)
{
b ^= 1;
for (int s = 0; s <= sa; s++)
for (int c = 0; c <= sb; c++)
{
dp[b][s][c] = dp[!b][s][c];
if (s < ai[i])
continue;
for (int idx = 0, acc = 1; idx < bi[i] && idx <= c; idx++, acc = 1LL * acc * ai[i] % mod)
dp[b][s][c] = (0LL + dp[b][s][c] + mod - 1LL * acc * inv[idx] % mod * dp[!b][s - ai[i]][c - idx] % mod) % mod;
}
}
int ans = 0;
for (int s = 0; s <= sa; s++)
{
int unit = fpow(s, mod - 2);
for (int idx = 0, acc = unit; idx <= sb; idx++, acc = 1LL * acc * unit % mod)
ans = (0LL + ans + 1LL * fac[idx] * acc % mod * dp[b][s][idx] % mod) % mod;
}
ans = 1LL * ans * sa % mod, printf("%d\n", ans);
return 0;
}