Educational Codeforces Round 113 (Rated for Div. 2)A~E
A. Balanced Substring
题意:给出一种仅包含ab字母的字符串,要求给出区间l,r,使得区间内的a,b字符数量相同,找不到输出-1 -1
分析:找到连续的ab或ba即可
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define x first
#define y second
#define MAX(a,b,c) max(max(a, b),c)
#define MIN(a,b,c) min(min(a, b),c)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5 + 10, mod = 1e9 + 7;
int n, m, t, k;
int s[N], dp[N], f[N];
char g[N];
string str;
vector<int> vec;
void solve()
{
cin >> n >> str;
for (int i = 1; i < n; i++)
{
if (str[i] != str[i-1])
{
printf("%d %d\n", i, i + 1);
return;
}
}
puts("-1 -1");
}
int main()
{
t = 1;
cin >> t;
while(t--)
solve();
return 0;
}
B. Chess Tournament
题意:所有队员只有两种想法,1,不败一场。2,至少能胜一场,输入n,输入长度为n的仅包含1和2的字符串,问是否存在满足所有队员的情况,i对j,胜利为'+',失败为'-',平局为'=',i=j为'X',不存在输出NO,存在输出YES,并输出n*n的状态
分析:对于要求不败的同学,可以均为平局,对于要求胜利一场的同学,可以查询与他对战的所有队伍,如果当前未确定状态,可以定为i对j胜利,j对i失败,存在不符合条件的输出NO,都符合输出YES,输出答案即可
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define x first
#define y second
#define MAX(a,b,c) max(max(a, b),c)
#define MIN(a,b,c) min(min(a, b),c)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 50 + 10, mod = 1e9 + 7;
int n, m, t, k;
int s[N], dp[N], f[N];
char g[N][N];
string str;
vector<int> vec;
void solve()
{
cin >> n >> str;
for (int i = 0; i < str.size(); i++)
for (int j = 0; j < str.size(); j++)
g[i][j] = ' ';
for (int i = 0; i < str.size(); i++)
for (int j = 0; j < str.size(); j++)
if (i == j) g[i][j] = 'X';
else if (str[i] == '1') g[i][j] = g[j][i] = '=';
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '1') continue;
int flag = 1;
for (int j = 0; j < str.size(); j++)
{
if (i == j) continue;
if (g[i][j] == ' ')
{
flag = 0;
g[i][j] = '+';
g[j][i] = '-';
break;
}
}
if (flag)
{
puts("NO");
return;
}
}
puts("YES");
for (int i = 0; i < str.size(); i++)
{
for (int j = 0; j < str.size(); j++)
{
if (g[i][j] == ' ') g[i][j] = '=';
printf("%c", g[i][j]);
}puts("");
}
}
int main()
{
t = 1;
cin >> t;
while(t--)
solve();
return 0;
}
C. Jury Meeting
题意:每个人输出有一个要叙述的事件数,初始不确定每个人说话顺序,当轮到那个人时,如果此时没有要叙述的事件,那么跳过,否则叙述完成后,自己的事件数--,问有多少种发言顺序可以使得不存在一个人同时说两件事
分析:分析可得,将初始所有事件数排序后,如果最大值的个数大于1个,那么随便排都成立,答案就是n!,否则如果最大值个数为1,如果比次大值的值大于1,那么无论如何都不可能,答案就是0,否则要保证不管怎么排,都要有至少一个次大值排在最大值之后。每次枚举最大值的位置,算出当前不成立的情况,就是所有次大值都在左侧,统计cnt,最后用所有情况数一减就好了,就是n!-cnt
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define x first
#define y second
#define MAX(a,b,c) max(max(a, b),c)
#define MIN(a,b,c) min(min(a, b),c)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5 + 10, mod = 998244353;
int n, m, t, k;
int s[N], dp[N], f[N], in[N], inv[N];
char g[N];
string str;
vector<int> vec;
int ksm(int a, int b, int p)
{
int res = 1;
while (b)
{
if (b & 1) res = 1ll * res * a % p;
a = 1ll * a * a % p;
b >>= 1;
}
return res;
}
void init()
{
in[0] = inv[0] = in[1] = inv[1] = 1;
for (int i = 2; i < N; i++)
{
in[i] = 1ll * in[i-1] * i % mod;
inv[i] = 1ll * inv[i-1] * ksm(i, mod - 2, mod) % mod;
}
}
int C(int n, int m)
{
return 1ll * in[n] * inv[n-m] % mod * inv[m] % mod;
}
void solve()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> s[i];
sort(s, s + n);
if (s[n-1] == s[n-2])
{
printf("%d\n", in[n]);
return;
}
if (s[n-1] - s[n-2] > 1)
{
printf("0\n");
return;
}
int cnt = 0;
for (int i = 0; i < n; i++)
if (s[i] == s[n-2])
cnt++;
int ans = 0;
for (int i = cnt; i < n; i++)
ans = (1ll * ans + 1ll * C(i, cnt) * in[cnt] % mod * in[n-1-cnt] % mod) % mod;
printf("%d\n", (in[n] % mod - ans + mod) % mod);
}
int main()
{
init();
t = 1;
cin >> t;
while(t--)
solve();
return 0;
}
D. Expression Evaluation Error
题意:有n*m条街道,k个人,询问只能走街道的情况下,有多少个,两个人的最短距离大于他们的曼哈顿距离
分析:对于每两行街道中不同列的和每两列中不同行的都属于,这道题思路简单,代码麻烦,为简化代码,考虑统一计算,排除相同区间重复记过的数在一个区间内,对于行或列,重复的大小是当前相同区间内已经有的数量,行列分别计算
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define x first
#define y second
#define MAX(a,b,c) max(max(a, b),c)
#define MIN(a,b,c) min(min(a, b),c)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5 + 10, mod = 998244353;
int n, m, t, k;
int s[N], dp[N], f[N];
char g[N];
string str;
vector<int> vec;
map<int, int> ma;
map<PII, int> mb;
PII p[N];
void solve()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) cin >> s[i]; sort(s + 1, s + 1 + n);
for (int i = 1; i <= m; i++) cin >> f[i]; sort(f + 1, f + 1 + m);
for (int i = 1; i <= k; i++) cin >> p[i].x >> p[i].y;
ll ans = 0;
ma.clear(), mb.clear();
for (int i = 1; i <= k; i++)
{
int a = lower_bound(s+1, s+1+n, p[i].x) - s;
int b = lower_bound(f+1, f+1+m, p[i].y) - f;
if (s[a] == p[i].x && f[b] != p[i].y)
{
ans += ma[b]++;
ans -= mb[{a, b}]++;
}
}
ma.clear(), mb.clear();
for (int i = 1; i <= k; i++)
{
int a = lower_bound(s+1, s+1+n, p[i].x) - s;
int b = lower_bound(f+1, f+1+m, p[i].y) - f;
if (s[a] != p[i].x && f[b] == p[i].y)
{
ans += ma[a]++;
ans -= mb[{a, b}]++;
}
}
cout << ans << endl;
}
int main()
{
t = 1;
cin >> t;
while(t--)
solve();
return 0;
}
E. Non-Decreasing Dilemma
题意:两两淘汰制,第一为第一,第二为第二,第到第的排名为,计算h = (%998244353,pi为第i个人的排名,给定k,A,h,要求给出pi序列,若不存在输出-1,k<=5,A<=1e8,h余数范围内
分析:k的范围是5,对于所有情况枚举的话是就是是不够的,所以进一步看,发现如果不算左右两边的1和2的话,左右两边基本是基本相同的,所以考虑枚举,然后对于每个值枚举1和2的位置,用map记录查询,就是,代码实现较麻烦,预处理排名i对应的然后不改变位置,第一部分都是1到第二部分都是到,只改变他们的排名顺序,前一部分用
注:头文件numeric是函数iota(s, s + n, a)的头文件,该函数的作用是将区间的s变成以a为第一个数,d为1的等差数列
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <numeric>
#define x first
#define y second
#define MAX(a,b,c) max(max(a, b),c)
#define MIN(a,b,c) min(min(a, b),c)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5 + 10, mod = 998244353;
int n, m, t, k;
map<int, vector<int> > G(vector<int> iv, vector<int> V, vector<int> raw)
{
map<int, vector<int>>ret;
for(int i=0; i<1<<((int)iv.size()-1); ++i)
{
int ni = i;
vector<int> cur = {0};
for(int j=1; j<(int)V.size(); ++j)
{
vector<int> n;
for(int x: cur)
{
if(ni&1) n.push_back(x), n.push_back(j);
else n.push_back(j), n.push_back(x);
ni >>= 1;
}
cur = n;
}
int ans = 0;
vector<int> r(iv.size());
for(int i=0; i<(int)iv.size(); ++i)
ans = (1LL*iv[i]*V[cur[i]]+ans)%mod, r[i] = raw[cur[i]];
ret[ans] = r;
}
return ret;
}
void solve()
{
int A, h;
cin >> k >> A >> h;
vector<int> V(k), Vr(k);
V[0] = A, Vr[0] = 1;
for (int i = 1; i < k; i++) V[i] = 1ll * V[i-1] * V[i-1] % mod, Vr[i] = 2 * Vr[i-1];
for (int &x : Vr) ++x;
for (int &x : V) x = 1ll * x * A % mod;
vector<int> U = V, Ur = Vr;
U[0] = A; Ur[0] = 1;
vector<int> X(1 << (k-1)), Y(1 << (k-1));
iota(X.begin(), X.end(), 1);
iota(Y.begin(), Y.end(), 1 + (1 << (k-1)));
for (int i = 0; i < 2; i++)
{
auto M1 = G(X, U, Ur);
auto M2 = G(Y, V, Vr);
map<int, vector<int> >::reverse_iterator iter;
for(iter = M1.rbegin(); iter != M1.rend(); iter++)
{
int a = iter->first;
vector<int> b = iter->second;
int targ = h-a; if (targ < 0) targ += mod;
auto it = M2.find(targ);
if(it != M2.end())
{
for(auto x: b) cout << x << " ";
for(auto x: it->second) cout << x << " ";
cout << endl;
return;
}
}
swap(U, V);
swap(Ur, Vr);
}
cout << -1 << endl;
}
int main()
{
t = 1;
// cin >> t;
while(t--)
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!