SMU Summer 2024 Contest Round 7
A Make Equal With Mod
思路:
首先x >= 2,那么对于出现1的时候就没有办法处理,所以需要把所有数都变为1,从最大的数开始,每个数 mod 这个数减一 后得到1,只有当出现两个数的差为1时没有办法把全部树变为1
当没有出现1时,所有数都可以通过mod 自己 后得到0
void solve() {
int n;
cin >> n;
vector<int> ve(n);
bool ok1 = false;
for (int i = 0; i < n; ++i) {
cin >> ve[i];
if (ve[i] == 1) ok1 = true;
}
if (ok1) {
sort(ve.begin(), ve.end());
for (int i = 1; i < ve.size(); ++i) {
if (ve[i] - ve[i - 1] == 1) {
cout << "NO\n";
return ;
}
}
}
cout << "YES\n";
}
B Game on Ranges
思路:
贪心的先处理区间长度小的,枚举找到可行的数
struct E {
int l, r, ans;
bool operator<(const E &e)const {
return (r - l) < (e.r - e.l);
}
};
void solve() {
int n;
cin >> n;
vector<E> ve(n);
for (int i = 0; i < n; ++i) cin >> ve[i].l >> ve[i].r;
sort(ve.begin(), ve.end());
vector<int> st(n + 1), g;
for (int i = 0; i < n; ++i) {
for (int j = ve[i].l; j <= ve[i].r; ++j) {
if (!st[j]) {
ve[i].ans = j;
st[j] = 1;
break;
}
}
}
for (int i = 0; i < n; ++i) {
cout << ve[i].l << ' ' << ve[i].r << ' ' << ve[i].ans << '\n';
}
// cout << '\n';
}
C Buy an Integer
思路:
x是顺着n的增加而增加的,可以二分来做
void solve() {
int a, b, x;
cin >> a >> b >> x;
int l = 1, r = 1e9, ans = 0;
auto check = [=] (int u) {
int cnt = 0, y = u;
while (y) {
cnt ++, y /= 10;
}
int s = a * u + b * cnt;
return s <= x;
};
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1, ans = mid;
else r = mid - 1;
}
cout << ans;
}
D String Formation
思路:
标记下当前串的翻转状态,每次插入操作,根据当前串的状态来插入
void solve() {
string s;
cin >> s;
string g[2];
int op = 0;
int q;
cin >> q;
while (q --) {
int t;
cin >> t;
if (t == 1) {
op ^= 1;
} else if (t == 2) {
char c;
cin >> t >> c;
if (t == 1) {
g[op].push_back(c);
} else if (t == 2) {
g[op ^ 1].push_back(c);
}
}
}
for (int i = g[op].size() - 1; i >= 0; --i) cout << g[op][i];
if (op == 1) std::reverse(s.begin(), s.end());
cout << s;
cout << g[op ^ 1];
}
E Bouquet
思路:
花的种类不同,那么一共有2n - 1种选法(不能不选),由于花的数量不能为a或b,不能有n朵里选a或b朵,即C(n, a)和 C(n, b),这里n很大,且模数为质数,可以用lucas求组合数
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
const int N = 1e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int ksm(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % Mod;
b >>= 1;
a = a * a % Mod;
}
return res;
}
int C(int a, int b, int p) {
if (b > a) return 0;
int res = 1;
for (int i = 1, j = a; i <= b; ++i, --j) {
res = (int)res * j % p;
res = (int)res * ksm(i, p - 2) % p;
}
return res;
}
int lucas(int a, int b, int p) { // 注意int参数类型
if (a < p && b < p) return C(a, b, p);
return (int)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p; // 递归让其到p范围内求解
}
void solve() {
int n, a, b;
cin >> n >> a >> b;
int ans = (ksm(2, n) - 1 + Mod ) % Mod;
// cout << ans << '\n';
ans = ((ans - C(n, a, Mod) + Mod) % Mod - C(n, b, Mod) + Mod) % Mod;
cout << ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}
F Permutation
G String Cards
思路:
贪心+dp
对于两个串a、b,通过比较a + b 和 b + a可以知道a和b的先后顺序
在考虑dp求后i个串中选j个的最小串
这里有个误区,求的是后i个串中选j个的最小串(而不是前i个)
为什么呢,求一个字典序最小的串,应该是从第一个字符开始找最小的,所以应该枚举的是第一个串放与不放,则为倒着枚举第一个串放与不放,如果为正着枚举就是考虑的最后一个串放与不放
bool cmp(string a, string b) {
return a + b < b + a;
}
void solve() {
int n, k;
cin >> n >> k;
vector<string> ve(n + 1);
for (int i = 1; i <= n; ++i) cin >> ve[i];
sort(ve.begin() + 1, ve.end(), cmp);
vector<vector<string> > f(n + 5, vector<string> (k + 5, "~"));
for (int i = 1; i <= n + 1; ++i) f[i][0] = "";
for (int i = n; i >= 1; --i) {
for (int j = 1; j <= k && j <= n - i + 1; ++j) {
f[i][j] = min(f[i + 1][j], ve[i] + f[i + 1][j - 1]);
}
}
cout << f[1][k];
}

浙公网安备 33010602011771号