模拟赛SXJ202507300900比赛记录&题解
题目请看
T1
跟着题目进行模拟,关键在于匹配字符串。
输出要用mod进行优化一下回使代码更加简洁。
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int N = 50 + 5;
int n;
bool flag[27];
char zm[28] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string s[N], str;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
int main() {
ios
// fre("1")
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> s[i];
}
cin >> str;
for (int i = 1; i <= n; i ++) {
bool kmp = true;
for (int j = 0; j < str.size(); j ++) {
if (str[j] != s[i][j]) {
kmp = false;
}
}
if (kmp) {
if (s[i][str.size()] >= 'A' && s[i][str.size()] <= 'Z') {
flag[s[i][str.size()] - 'A' + 1] = true;
}
}
}
// for (int i = 1; i <= 26; i ++) {
// cout << flag[i] << endl;
// }
int now = 1;
for (int i = 1; i <= 32; i ++) {
if (i <= 3) {
cout << "*";
continue ;
}
if (i >= 30) {
cout << "*";
continue ;
}
if (flag[now]) {
cout << zm[now];
} else {
cout << "*";
}
now ++;
if (i % 8 == 0) {
cout << endl;
}
}
return 0;
}
赛时:100point
赛后:无
T2
题目其实就是让我们先对客人价格进行排序。
看一下
\(max_{i=1}^{i<=n}\)
\(定a_i作为单价让后n-i个人付得起钱\)
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int N = 2 * 1e5 + 5;
ll n, a[N], ans, now;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
int main() {
ios
// fre("1")
n = read();
for (ll i = 1; i <= n; i ++) {
a[i] = read();
}
// for (ll i = 1; i <= n; i ++) {
// cout << a[i] << endl;
// }
sort(a + 1, a + 1 + n);
for (ll i = 1; i <= n; i ++) {
now = a[i] * (n - i + 1);
ans = max(ans, now);
}
cout << ans;
return 0;
}
赛时:100point
赛后:无
T3
大模拟,不难发现对于每次扩展,只是在右下角扩展出一个不同的,而其他地方保持不变
可以得到以下思路
int dx = 2 * i;//i为当前扩展的行
int dy = 2 * j;//j为当前扩展的列
//扩展
cnt[dx][dy] = cnt[dx][dy + 1] = cnt[dx + 1][dy] = pos;//pos为cnt[i][j]的数值
cnt[dx + 1][dy + 1] = (pos == '0') ? '1' : '0';
//cnt为当前扩展后的答案
在这里我建议直接用vector<string> ans(1, string(1, ('0' + val)));
,这样可以直接取size
做大小
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int N = 2048 + 5;
string s[N];
int n, val;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
int main() {
ios
// fre("")
cin >> n >> val;
if (n == 0) {
cout << val;
return 0;
}
vector<string> ans(1, string(1, ('0' + val)));//当一回sb,主要是size太好用了
// cout << ans[0][0];
for (int k = 1; k <= n; k ++) {
int x = ans.size();
int y = ans[0].size();
vector<string> cnt(2 * x, string(2 * y, '0'));
for (int i = 0; i < x; i ++) {
for (int j = 0; j < y; j ++) {
char pos = ans[i][j];
int dx = 2 * i;
int dy = 2 * j;
cnt[dx][dy] = cnt[dx][dy + 1] = cnt[dx + 1][dy] = pos;
cnt[dx + 1][dy + 1] = (pos == '0') ? '1' : '0';
}
}
ans = cnt;
}
for (int i = 0; i < ans.size(); i ++) {
for (int j = 0; j < ans[0].size(); j ++) {
cout << ans[i][j];
}
cout << endl;
}
return 0;
}
/*
其实每次扩展就是在一个4*4平面的右下角扩展一个不一样的
*/
赛时:100point
赛后:无
T4
其实不难看出是一道图论题目,链式前向星建好边后只需要bfs
全部前置技巧即可
贴一下代码
#include<bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int maxn=2 * 1e5 + 5;
struct Edge {
int to;
int next;
} edge[maxn];
int head[maxn];
ll t[maxn];
queue<int >q;
bool vis[maxn];
int tot=0;
void link(int u,int v) {
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot ++;
}
int main() {
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
int k;
cin >> t[i] >> k;
for(int j = 0; j < k; j ++) {
int a;
cin >> a;
link(i,a);
}
}
ll to = 0;
q.push(n);
vis[n] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
to += t[u];
for(int i = head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].to;
if(!vis[v]) {
vis[v]=true;
q.push(v);
}
}
}
cout<<to;
return 0;
}
赛时:12point
赛后:100point
T5
先补充一个知识点:
回文序列的性质:对于一个回文序列,对称位置的元素必须相同。即对于位置
i
和位置n-i+1
的元素必须相同。
我们可以使用并查集来管理需要合并的馅料编号。对于每一对对称位置的馅料编号,如果它们不同,我们需要将它们合并到同一个集合中。合并操作代表了我们需要将这些馅料统一成同一个编号。
每次合并两个不同的馅料编号集合时,相当于进行了一次替换操作。因此,最少操作次数等于需要合并的不同馅料对数。
-
初始化并查集:为每个馅料编号初始化一个独立的集合。
-
处理对称位置:遍历序列的前半部分,对于每个位置i,检查\(a_i\)和\(a_{n-i+1}\)是否相同:
- 如果不同,使用并查集合并这两个馅料编号所在的集合。
-
统计操作次数:遍历所有馅料编号,统计每个集合的代表元素。操作次数等于不同集合的数量减去1(因为最终所有需要合并的馅料都会属于同一个集合)。
贴一下标程
#include<bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int N = 2 * 1e5 + 5;
map<int,map<int,int> > mp;
int n,a[N],sum[N],f[N],ans;
int find(int x){
return x!=f[x]?f[x]=find(f[x]):x;
}
int main(){
ios
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
f[a[i]]=a[i];
sum[a[i]]=1;
}
for(int i=1;i<=n/2;i++){
if(find(a[i])!=find(a[n-i+1])){
a[n-i+1]=find(a[n-i+1]);
a[i]=find(a[i]);
sum[a[i]]+=sum[a[n-i+1]];
sum[a[n-i+1]]=0;
f[a[n-i+1]]=a[i];
}
}
for(int i=1;i<=n;i++){
ans+=sum[find(a[i])]-1;
sum[find(a[i])]=1;
}
cout << ans;
return 0;
}
赛时:6point
赛后:100point