A
按照题意输出即可。
时间复杂度:
空间复杂度:
#include <iostream>
using namespace std;
int n;
void Solve() {
cin >> n;
string s(n, 'a');
cout << s << 'b' << s;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
B
考虑对长度为 和
的前缀答案做差。
观察可得答案约等于长度除以三,手玩一下公式前几项防止出错。
时间复杂度:
空间复杂度:
#include <iostream>
using namespace std;
int l;
int r;
void Solve() {
cin >> l >> r;
l--;
for (int i = 2; i > -1; i--) {
cout << (r + i) / 3 - (l + i) / 3 << ' ';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
C
不妨令 。
若 ,马无法跳,答案为
;
若 ,马只能向左右方向跳,答案为
;
若 ,中间的格子马无法跳,而剩下八个格子通过一个类似五角星形状的转圈可以全部互相到达,答案为
;
若 ,可以通过两个
的形状使得所有点都可以互相到达,故答案为
;
更大时同理,答案为
。
时间复杂度:
空间复杂度:
#include <iostream>
using namespace std;
using ll = long long;
int n;
int m;
ll Res() {
if (n > m) {
swap(n, m);
}
if (n == 1) {
return 1;
}
if (n == 2) {
return (m + 1) / 2;
}
if (m == 3) {
return 8;
}
return (ll)m * n;
}
void Solve() {
cin >> n >> m;
cout << Res();
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
D
考虑 是
和
的公倍数,所以小数点后长度
位一定是循环节。由于
,故长度为
符合要求。将
和
的循环节都不断重复至长度
。
如果这时 的循环节大于
的循环节,则直接作高精度减法就是答案。否则,做
的高精度减法,然后因为
将所有的位
改为
即可。
时间复杂度:
空间复杂度:
#include <iostream>
using namespace std;
using ll = long long;
int n;
int m;
string a;
string b;
void Solve() {
cin >> n >> m >> a >> b;
int k = n * m;
string res;
res.reserve(k);
for (int i = 0; i < m; i++) {
res += a;
}
string resb;
resb.reserve(k);
for (int i = 0; i < n; i++) {
resb += b;
}
bool reverse = false;
if (res < resb) {
swap(res, resb);
reverse = true;
}
for (int i = k - 1; i > -1; i--) {
res[i] -= resb[i] - '0';
if (res[i] < '0') {
res[i] += 10;
res[i - 1]--;
}
}
if (reverse) {
for (auto& c : res) {
c = 9 - (c - '0') + '0';
}
}
cout << k << '\n' << res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
E
发现题目描述等价于对每一个子树求最深非叶子节点的数量。考虑 DP。
记录最深非叶子节点的深度以及数量,搜索时不断合并自身和新子树的信息。合并时,如果深度不同保留更深的深度和数量,否则将数量求和,深度不变。
时间复杂度:
空间复杂度:
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
int n;
vector<vector<int>> graph;
vector<pii> res;
void Dfs(int x, int fa, int h) {
bool leaf = true;
int maxh = 0;
int sz = 0;
for (const auto& y : graph[x]) {
if (y != fa) {
if (leaf) {
leaf = false;
if (h > maxh) {
maxh = h;
sz = 1;
}
else if (h == maxh) {
sz++;
}
}
Dfs(y, x, h + 1);
auto [yh, ysz] = res[y];
if (yh > maxh) {
maxh = yh;
sz = ysz;
}
else if (yh == maxh) {
sz += ysz;
}
}
}
res[x] = {maxh, sz};
}
void Solve() {
cin >> n;
graph.resize(n + 1);
res.resize(n + 1);
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
Dfs(1, 0, 0);
for (int i = 1; i <= n; i++) {
cout << res[i].second << ' ';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
F
考虑前缀做差,设长度为 的前缀为
。答案为
。
考虑将长度为 的前缀分为两部分:长度为
的前半部分以及长度为
的后半部分。后半部分直接暴力求解。前半部分等于
。这个式子可以用等比数列求和公式快速求出。
使用快速幂来计算这些式子,注意随时取模。
时间复杂度:
空间复杂度:
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int MOD = 998244353;
ll Pow(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 Inv(ll a) {
return Pow(a, MOD - 2);
}
int n;
ll l;
ll r;
string x;
ll valx;
ll base;
// 10**
ll Pre(ll r) {
ll t = r / n;
int yu = r % n;
ll val = 0;
for (int i = 0; i < yu; i++) {
val = (val * 10 + (x[i] - '0')) % MOD;
}
if (base == 1) {
val = (val + valx * t % MOD * Pow(10, yu)) % MOD;
}
else {
val = (val + (Pow(base, t) - 1) * Inv(base - 1) % MOD * valx % MOD * Pow(10, yu)) % MOD;
}
return val;
}
void Solve() {
cin >> n >> l >> r >> x;
valx = 0;
for (const auto& c : x) {
valx = (valx * 10 + (c - '0')) % MOD;
}
base = Pow(10, n);
ll res = (Pre(r) - Pre(l - 1) * Pow(10, r - l + 1)) % MOD;
if (res < 0) {
res += MOD;
}
cout << res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}

京公网安备 11010502036488号