A. Forbidden Integer
分类讨论
如果不禁 ”1“, 则可以达成任何数
如果禁 ”1“ 且 k ≥ 3 k \ge 3 k≥3,则可以达成任何大于等于2的数
特判一下 k k k 的范围
#include <bits/stdc++.h>
//#include "LocalDebug.h"
using namespace std;
#define int long long
#define pb push_back
#define VI vector<int>
const int inf = 0x3f3f3f3f;
const long long llinf = (long long)0x3f3f3f3f3f3f3f3f;
const long long MOD = (long long)1e9 + 7LL;
const size_t N = (size_t)1e6 + 5;
#define IO \
ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0)
void solve() {
int n, k, x;
cin >> n >> k >> x;
if (x != 1) {
cout << "YES\n" << n << endl;
for (int i = 0; i < n; i++) {
cout << "1 ";
}
cout << endl;
return;
}
if (k == 1){
cout << "NO\n";
}
if (k == 2) {
if (!(n & 1)) {
cout << "YES\n" << n / 2 << endl;
for (int i = 0; i < n / 2; i++) {
cout << "2 ";
}
cout << endl;
return;
}
else {
cout << "NO\n";
}
}
if (k > 2) {
cout << "YES\n";
if (n & 1) {
cout << n / 2 << endl;
for (int i = 0; i < n / 2 - 1; i++) {
cout << "2 ";
}
cout << "3 " << endl;
return;
}
else {
cout << n / 2 << endl;
for (int i = 0; i < n / 2; i++) {
cout << "2 ";
}
cout << endl;
return;
}
}
}
signed main() {
IO;
int T;
T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
B. Come Together
将坐标拆分成x方向和y方向两个方向来处理
若一方向上B点和C点基于A点的偏移量正负性相同,则可以取二者偏移量绝对值中的较小值作为贡献值
最后将两个方向上的贡献值加在一起即可
注意ans
的初始值应为1
#include <bits/stdc++.h>
//#include "LocalDebug.h"
using namespace std;
#define int long long
#define pb push_back
#define VI vector<int>
const int inf = 0x3f3f3f3f;
const long long llinf = (long long)0x3f3f3f3f3f3f3f3f;
const long long MOD = (long long)1e9 + 7LL;
const size_t N = (size_t)1e6 + 5;
#define IO \
ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0)
void solve() {
int xa, ya, xb, yb, xc, yc;
cin >> xa >> ya >> xb >> yb >> xc >> yc;
xb -= xa; yb -= ya; xc -= xa; yc -= ya;
int ans = 1;
if ((xb > 0 && xc > 0) || (xb < 0 && xc < 0)) {
ans += min(abs(xb), abs(xc));
}
if((yb > 0 && yc > 0) || (yb < 0 && yc < 0)) {
ans += min(abs(yb), abs(yc));
}
cout << ans << endl;
}
signed main() {
IO;
int T;
T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
C. Strong Password
构造子序列自动机
将 l i l_i li 到 r i r_i ri 之间的数进行枚举,若最终能达到状态 n + 1 n + 1 n+1 ,则说明能够生成非 s s s 子序列的字符串
#include <bits/stdc++.h>
//#include "LocalDebug.h"
using namespace std;
#define int long long
#define pb push_back
#define VI vector<int>
const int inf = 0x3f3f3f3f;
const long long llinf = (long long)0x3f3f3f3f3f3f3f3f;
const long long MOD = (long long)1e9 + 7LL;
const size_t N = (size_t)1e6 + 5;
#define IO \
ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0)
void solve() {
string s;
cin >> s;
int n = s.size();
vector<array<int, 10>> nxt(n + 1);
nxt[n].fill(n + 1);
for(int i = n - 1; i >= 0; i--) {
nxt[i] = nxt[i + 1];
nxt[i][s[i] - '0'] = i + 1;
}
int m;
cin >> m;
string ls, rs;
cin >> ls >> rs;
int p = 0;
for (int i = 0; i < m; i++) {
int l = ls[i] - '0';
int r = rs[i] - '0';
int t = 0;
for (int j = l; j <= r; j++) {
t = max(t, nxt[p][j]);
}
p = t;
if (p == n + 1) break;
}
cout << ((p == n + 1) ? "YES\n" : "NO\n");
}
signed main() {
IO;
int T;
T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
D. Rating System
本题要让保底 k k k 尽可能大抵消掉和为负的子序列
则问题可以简化成:找出最小子段和,输出该子段前一位的前缀和
#include <bits/stdc++.h>
//#include "LocalDebug.h"
using namespace std;
#define int long long
#define pb push_back
#define VI vector<int>
const int inf = 0x3f3f3f3f;
const long long llinf = (long long)0x3f3f3f3f3f3f3f3f;
const long long MOD = (long long)1e9 + 7LL;
const size_t N = (size_t)1e6 + 5;
#define IO \
ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0)
void solve() {
int n;
cin >> n;
int ans = 0, mx = 0, sum = 0, mk = 0, mi = 0;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
sum += x;
mx = max(mx, sum);
mi = sum - mx;
if (mi < mk) {
mk = mi;
ans = mx;
}
}
cout << ans << endl;
}
signed main() {
IO;
int T;
T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}