Rayan Programming Contest 2024 - Selection (Codeforces Round 989, Div. 1 + Div. 2)题解记录(A~E)
比赛链接:https://codeforces.com/contest/2034
本场不是赛时也不是vp的,单纯赛后补的,现在看来怎么感觉比上次的edudiv2更简单些?
A. King Keykhosrow's Mystery
题面:
有一个关于睿智的国王 Keykhosrow 的故事,他拥有一个宏伟的宝库,里面装满了来自波斯帝国各地的宝藏。然而,为了防止盗窃和确保他的财富安全,Keykhosrow 国王的金库被一把神奇的锁封住了,只有解开谜题才能打开。
这个谜题涉及到两个神圣的数字
必须大于或等于 和 中的至少一个。- 当
被 除时的余数必须等于 被 除时的余数。
只有找到
输入:
第一行包含一个整数
每个测试用例由一行组成,包含两个整数
输出:
对于每个测试用例,打印满足上述条件的最小整数
样例:
2
4 6
472 896
12
52864
思路:
做法一:显然
做法二:直接求lcm,最小公倍数。因为
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll a,b;
cin>>a>>b;
ll u=gcd(a,b);
cout<<a/u*b<<endl;
}
return 0;
}
B. Rakhsh's Revival
题面:
Rostam的忠实马 Rakhsh的日子好过。曾经强大而快速的 Rakhsh 随着时间的推移变得越来越虚弱,甚至难以移动。Rostam 担心,如果 Rakhsh 身体的太多部位同时失去力量,Rakhsh 可能会完全停止。为了让他的同伴继续前进,Rostam 决定一点一点地加强 Rakhsh,这样他身体的任何部分都不会太脆弱太久。
将 Rakhsh 的身体想象成一行点,由长度为
幸运的是,Rostam 有一种叫做 Timar 的特殊能力,是他出生时从他的母亲 Rudabeh 那里继承的。使用 Timar,他可以选择任何长度
输入:
第一行包含一个整数
每个测试用例的第一行包含三个数字
保证所有测试用例的
输出:
对于每个测试用例,输出 Rostam 需要使用 Timar 保持 Rakhsh 移动的最小次数,确保没有长度为
样例:
3
5 1 1
10101
5 2 1
10101
6 3 2
000000
———————
2
0
1
思路:最优方法应该是你在不符合的情况下放一个块使之符合答案,所以统计区间段,一旦区间段不符合,就以这个为左端点设置加强段
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,m,k;
cin>>n>>m>>k;
string f;
cin>>f;
ll cnt=0;
ll ans=0;
ll dx=0;
for(ll i=0;i<f.size();i++)
{
if(f[i]=='0'&&dx==0)
{
cnt++;
}
if(cnt==m)
{
cnt=0;
dx=k;
ans++;
}
if(f[i]=='1')
cnt=0;
dx--;
dx=max(dx,(ll)0);
}
cout<<ans<<endl;
}
return 0;
}
C. Trapped in the Witch's Labyrinth
题面:
在 Rostam的第四个任务 中,来自 Shahnameh 的传奇英雄,一位老巫婆创造了一个魔法迷宫来困住他。迷宫是一个由
如果 Rostam 最终走出迷宫,他将从巫婆的咒语中解脱出来并击败她。然而,如果他永远被困在迷宫中,他将永远无法逃脱。
巫婆还没有确定所有单元格的方向。她想要以一种方式分配方向给未指定的单元格,使得 Rostam 将永远被困住的起始单元格数量最大化。您的任务是找出使 Rostam 被困的起始单元格的最大数量。
输入:
第一行的输入包含一个整数
对于每个测试用例:
- 第一行包含两个整数
和 ( ),代表迷宫中的行数和列数。 - 接下来的
行,每行包含一个由 个字符组成的字符串,表示迷宫中的方向。每个字符是以下之一:- U (上)
- D (下)
- L (左)
- R (右)
- ? (未指定的方向)
保证所有测试用例的
输出:
对于每个测试用例,打印一个整数,这是在为未指定的单元格分配方向后,Rostam将永远被困住的最大起始单元格数量。
样例:
3
3 3
UUU
L?R
DDD
2 3
???
???
3 3
?U?
R?L
RDL
————
0
6
5
思路:思考不合法方案。对于外围一圈,如果箭头只想外面必定不符合,所以写个dfs对于这些不符合的点进行深搜,这个深搜每次去看周围有没有指向自己的箭头,有就继续搜并打上标记。如何解决?,可以发现对于每个不合法的点可以对于他四周进行次数标记,如果一个?被打过4次标记,他就什么方向都不行,也就是不合法点。所以最后遍历一遍,对于?统计没标记过四次的,对于箭头统计没记过的
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
string f[2500];
bool vis[1005][1005];
ll fk[1005][1005];
ll u[5]={0,0,1,0,-1};
ll d[5]={0,1,0,-1,0};
char g[5]={'0','L','U','R','D'};
ll n,m;
void dfs(ll x,ll y)
{
vis[x][y]=1;
for(ll i=1;i<=4;i++)
{
ll nx=x+u[i];
ll ny=y+d[i];
fk[nx][ny]++;
if(vis[nx][ny]||nx<1||ny<1||nx>n||ny>m||g[i]!=f[nx][ny])
continue;
dfs(nx,ny);
}
}
bool vi[10005][1005];
ll ck(ll x,ll y)
{
if(vi[x][y])return 0;
vi[x][y]=1;
if(f[x][y]=='?')
{
for(ll i=1;i<=4;i++)
{
ll nx=x+u[i];
ll ny=y+d[i];
if(nx<1||ny<1||nx>n||ny>m)
fk[x][y]++;
}
}
if(f[x][y]=='U')
{
if(x-1<1)
return 1;
}
if(f[x][y]=='D')
{
if(x+1>n)
return 1;
}
if(f[x][y]=='R'&&y+1>m)
return 1;
if(f[x][y]=='L'&&y-1<1)
return 1;
return 0;
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(ll i=1;i<=n;i++)
{
cin>>f[i];
f[i]='0'+f[i];
}
for(ll i=0;i<=n;i++)
{
for(ll j=0;j<=m;j++)vis[i][j]=fk[i][j]=vi[i][j]=0;
}
for(ll j=2;j<=m-1;j++)
{
fk[1][j]++;
if(f[1][j]=='U')
{
dfs(1,j);
}
}
//fk[1][1]+=2,fk[1][m]+=2;
if(ck(1,1))dfs(1,1);
// cout<<fk[1][1]<<endl;
if(ck(1,m))dfs(1,m);
for(ll j=2;j<=n-1;j++)
{
fk[j][m]++;
if(f[j][m]=='R')
dfs(j,m);
}
// fk[n][m]+=2;
if(ck(n,m))dfs(n,m);
for(ll j=2;j<=m-1;j++)
{
fk[n][j]++;
if(f[n][j]=='D')
dfs(n,j);
}
//fk[n][1]+=2;
if(ck(n,1))dfs(n,1);
for(ll j=2;j<=n-1;j++)
{
fk[j][1]++;
if(f[j][1]=='L')
dfs(j,1);
}
ll ans=0;
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=m;j++)
{
if(vis[i][j])continue;
if(f[i][j]=='?'&&fk[i][j]<4)ans++;
if(f[i][j]!='?')ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
D. Darius' Wisdom
题面:
大流士 Darius 正在建造
在每一步中,Darius 可以选择两座石柱
由于美观是历史建筑的主要支柱,Darius 希望石柱的高度按铭文数量的非递减顺序排列。为了避免过度劳工人们的努力,他请求你计划一个最多
输入:
第一行包含一个整数
每个测试用例的第一行包含一个整数
第二行包含
保证所有测试用例的
输出:
对于每个测试用例,输出一个整数
然后,输出
可以证明,在给定的约束条件下,总存在一个有效的解决方案。
样例:
3
4
0 2 0 1
3
1 2 0
6
0 1 1 2 2 2
————————————
2
2 4
2 3
2
3 1
2 3
0
思路:这题的代码量比上题少多了,先统计0,1的数量,然后开三个set,分别储存0,1,2的位置,从前往后遍历,
如果这个位置得是0,但是是1,那就把最远得0和现在得1交换位置。顺便更新下set容器,如果是2,就先把此时的2和最远的1交换,然后再把现在的1和最远的0交换。
如果这个位置得是1,但是是2,那就把最远的1和现在的2交换下位置。
如果这个位置得是2时,早以解决,直接break
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll p=rnd()%mod;
const ll maxn=2e5+15;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[250000];
ll b[5];
set<ll>q[4];
vector<pair<ll,ll>>g;
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
g.clear();
q[1].clear();
q[2].clear();
q[0].clear();
b[0]=b[1]=b[2]=0;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
b[a[i]]++;
if(a[i]==1)
q[1].insert(i);
else if(a[i]==2)
q[2].insert(i);
else q[0].insert(i);
}
for(ll i=1;i<=n;i++)
{
if(b[0]>0)
{
if(a[i]==0)b[0]--;
else if(a[i]==1)
{
auto u=q[0].rbegin();
q[0].insert(i);
q[1].erase(i);
q[1].insert(*u);
swap(a[*u],a[i]);
g.push_back({i,*u});
q[0].erase(*u);
b[0]--;
}
else
{
auto u=q[1].rbegin();
swap(a[*u],a[i]);
g.push_back({i,*u});
q[2].insert(*u);
q[1].erase(*u);
q[1].insert(i);
q[2].erase(i);
u=q[0].rbegin();
swap(a[*u],a[i]);
g.push_back({i,*u});
q[0].insert(i);
q[1].erase(i);
q[1].insert(*u);
q[0].erase(*u);
b[0]--;
}
}
else if(b[1]>0)
{
if(a[i]==1)b[1]--;
else
{
auto u=q[1].rbegin();
q[2].insert(*u);
q[1].insert(i);
q[2].erase(i);
swap(a[*u],a[i]);
g.push_back({i,*u});
b[1]--;
q[1].erase(*u);
}
}
else break;
}
cout<<g.size()<<endl;
for(auto x:g)
{
cout<<x.first<<" "<<x.second<<endl;
}
}
}
E. Permutations Harmony
题面:
Rayan 想向 Reyhaneh 赠送一份礼物,以赢得她的心。但是,Reyhaneh 很特别,并且只接受一组
我们定义一个
您的任务是帮助 Rayan,要么为给定的
我们称长度为
输入:
第一行包含一个整数
每个测试用例由两个整数
输出:
对于每个测试用例,如果存在一个
如果不存在这样的集合,请在第一行打印 "NO"。
在任何情况下,您都可以输出 “YES” 和 “NO”(例如,字符串 “yEs”、“yes” 和 “Yes” 将被识别为肯定响应)。
如果有多个答案,您可以输出其中任何一个。
样例:
4
3 3
4 2
5 1
3 2
YES
1 2 3
2 3 1
3 1 2
YES
1 2 3 4
4 3 2 1
NO
YES
1 2 3
3 2 1
思路:首先特判k=1时的情况。然后发现一个n序列的最多不同排序数为n!,如果k大于这个直接NO。
其实一个排列和另一个排列每列加起来等于n+1具有对称性,如:1 2 3 ,3 2 1,他们各占n!/2,如果k等于偶数,直接使用next_permutation(),全排列函数直接输出此时序列和对称序列,不要怕会重复,再重复之前,一定可以输出完答案的,到时候break就行了
如果k为奇数,首先得考虑
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9+7;
const ll p=rnd()%mod;
const ll maxn=2e5+15;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
bool vis[250000];
ll a[250000];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
for(ll i=1;i<=n;i++)
{
a[i]=i;
}
if(n==1&&k==1)
{
cout<<"YES"<<endl;
cout<<1<<endl;
continue;
}
if(k==1)
{
cout<<"NO"<<endl;
continue;
}
ll cnt=1;
ll pd=0;
for(ll j=1;j<=n;j++)
{
cnt*=j;
if(cnt>=k)
{
pd=1;
break;
}
}
if(pd==0)
{
cout<<"NO"<<endl;
continue;
}
if(k%2==0)
{
cout<<"YES"<<endl;
do
{
k-=2;
for(ll i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
for(ll i=1;i<=n;i++)
cout<<n+1-a[i]<<" ";
cout<<endl;
if(k==0)
break;
} while (next_permutation(a+1,a+1+n));
}
else
{
ll d=1;
ll pd=0;
for(ll i=1;i<=n;i++)
{
d*=i;
if(d-6>=k-3)
pd=1;
}
if(pd==0)
{
cout<<"NO"<<endl;
continue;
}
ll u=(1+n)*n/2*3;
map<ll,bool>mp;
if(u%n==0)
{
cout<<"YES"<<endl;
ll ha=0;
for(ll i=1;i<=n;i++)
{
cout<<i<<" ";
ha=((ha*p)%mod+i)%mod;
}
cout<<endl;
mp[ha]=1;
ha=0;
for(ll i=(n+1)/2;i<=n;i++)
{
cout<<i<<" ";
ha=((ha*p)%mod+i)%mod;
}
for(ll i=1;i<=(n+1)/2-1;i++)
{
cout<<i<<" ";
ha=((ha*p)%mod+i)%mod;
}
cout<<endl;
mp[ha]=1;
ha=0;
for(ll i=n;i>=1;i-=2)
cout<<i<<" ",ha=((ha*p)%mod+i)%mod;
for(ll i=n-1;i>=1;i-=2)
cout<<i<<" ",ha=((ha*p)%mod+i)%mod;
mp[ha]=1;
cout<<endl;
k-=3;
if(k>0)
{
do
{
ll ha1=0,ha2=0;
for(ll i=1;i<=n;i++)
ha1=(ha1*p%mod+a[i])%mod;
for(ll i=1;i<=n;i++)
ha2=(ha2*p%mod+n+1-a[i])%mod;
if(mp[ha1]==0&&mp[ha2]==0)
{
k-=2;
for(ll i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
for(ll i=1;i<=n;i++)
cout<<n+1-a[i]<<" ";
cout<<endl;
}
if(k==0)
break;
} while (next_permutation(a+1,a+1+n));
}
}
else
cout<<"NO"<<endl;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步