Codeforces Round 878 (Div3)
B. Binary Cafe
\(1 \leq n,k \leq 10^9\)
题解:思维
- 考虑两种情况
- 第一种:钱足够多,每种咖啡都可以买的情况下,答案为\(2^k\)
- 第二种:钱不够多,因为任一面值的钱数都有唯一的二进制表达方式,所以答案为\(n + 1\)
- 所以我们不妨先判断一下\(2^k\)有没有超过\(10^9\),如果超过了说明钱一定不够多,否则答案为\(min(2^k,n+1)\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;
void solve()
{
int n, k;
cin >> n >> k;
if (k >= 30)
{
cout << n + 1 << endl;
}
else
cout << min(n + 1, (1LL << k)) << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C. Ski Resort
题解:组合计数
- 我们不妨将连续的可以度假的时间看成一个线段
- 那么我们需要在这个线段中挑选连续的子线段作为一种方案
- 容易发现我们可以使用捆绑法后即可得到答案
- 假设线段长度为\(len\),且\(len >= k\),那么答案应该为\(\frac{(len - k + 1) \times (len - k + 2)}{2}\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;
int n, k, q;
int a[N];
int A(int a, int b)
{
int res = 1;
for (int i = a, j = 1; j <= b; --i, ++j)
{
res *= a;
}
return res;
}
void solve()
{
cin >> n >> k >> q;
for (int i = 1; i <= n; ++i)
cin >> a[i];
// cout << n << " " << k << " " << q << endl;
int len = 0;
int ans = 0;
for (int i = 1; i <= n; ++i)
{
if (a[i] <= q)
len++;
else
{
if (len >= k)
{
int t = len;
while (t >= k)
{
ans += A(t - k + 1, 1);
t--;
}
}
len = 0;
}
}
if (len >= k)
{
int t = len;
while (t >= k)
{
ans += A(t - k + 1, 1);
t--;
}
}
cout << ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
E. Character Blocking
题解:模拟
- 我们不妨记录初始状态下两个字符串之间有\(cnt\)个字符不相同
- 对于封锁操作以及解锁我们可以利用邻接表思想实现
- 对于交换操作,我们正常模拟,并维护\(cnt\)
- 对于检查操作,如果\(cnt=0\),那么相等,否则不相等
- 所以整个模拟过程的核心就是维护好两个字符串之间有多少个字符不相同
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 4e5 + 10, M = 4e5 + 10;
int t, q;
vector<int> g[N];
void solve()
{
string s1, s2;
cin >> s1 >> s2;
cin >> t >> q;
for (int i = 1; i <= q + 10; ++i)
g[i].clear();
int cnt = 0;
for (int i = 0; i < s1.size(); ++i)
if (s1[i] != s2[i])
cnt++;
s1 = " " + s1;
s2 = " " + s2;
vector<int> vis(s1.size() + 10);
// cout << cnt << endl;
for (int i = 1; i <= q; ++i)
{
int op, p, l, r, p1, p2;
cin >> op;
while (g[i].size())
{
int pos = g[i].back();
vis[pos] = 0;
if (s1[pos] != s2[pos])
cnt++;
g[i].pop_back();
}
if (op == 1)
{
cin >> p;
vis[p] = 1;
g[i + t].push_back(p);
if (s1[p] != s2[p])
cnt--;
}
else if (op == 2)
{
cin >> l >> p1 >> r >> p2;
if (l == 1 && r == 1)
{
if (s1[p1] != s2[p1] && !vis[p1])
cnt--;
if (s1[p2] != s2[p2] && !vis[p2])
cnt--;
swap(s1[p1], s1[p2]);
if (s1[p1] != s2[p1] && !vis[p1])
cnt++;
if (s1[p2] != s2[p2] && !vis[p2])
cnt++;
}
else if (l == 1 && r == 2)
{
if (s1[p1] != s2[p1] && !vis[p1])
cnt--;
if (s1[p2] != s2[p2] && !vis[p2])
cnt--;
swap(s1[p1], s2[p2]);
if (s1[p1] != s2[p1] && !vis[p1])
cnt++;
if (s1[p2] != s2[p2] && !vis[p2])
cnt++;
}
else if (l == 2 && r == 1)
{
if (s1[p1] != s2[p1] && !vis[p1])
cnt--;
if (s1[p2] != s2[p2] && !vis[p2])
cnt--;
swap(s2[p1], s1[p2]);
if (s1[p1] != s2[p1] && !vis[p1])
cnt++;
if (s1[p2] != s2[p2] && !vis[p2])
cnt++;
}
else if (l == 2 && r == 2)
{
if (s1[p1] != s2[p1] && !vis[p1])
cnt--;
if (s1[p2] != s2[p2] && !vis[p2])
cnt--;
swap(s2[p1], s2[p2]);
if (s1[p1] != s2[p1] && !vis[p1])
cnt++;
if (s1[p2] != s2[p2] && !vis[p2])
cnt++;
}
}
else
{
if (cnt == 0)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}