2024.11.30 Rayan Programming Contest 2024 - Selection (Codeforces Round 989, Div. 1 + Div. 2)

Solved: 5/10

Upsolved: 6/10

Rank: 329


数数水平真的太差了。。。F1 赛时对着期望和概率各种乱搞,结果发现把期望扔了就是道格路计数(


A. King Keykhosrow's Mystery

题意:给 a,b,求最小的 m 使得 mmoda=mmodb

输出最小公倍数即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
ll n,m;
cin>>n>>m;
cout<<n*m/__gcd(n,m)<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

B. Rakhsh's Revival

题意:给一个01串,每次操作可将长度为 k 的子串覆盖为 1,问最少几次操作可使串中不存在长度为 m 的全 0 子串。

遍历,遇到长度为 m 的子串就从第 m 个 0 开始覆盖。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n,m,k;
string s;
cin>>n>>m>>k>>s;
int len=0,res=0;
for(int i=0;i<n;++i){
if(s[i]=='0'){
++len;
if(len==m){
for(int j=0;j<k&&i+j<n;++j)s[i+j]='1';
++res,len=0;
}
}
else len=0;
}
cout<<res<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

C. Trapped in the Witch's Labyrinth

题意:一个上下左右四箭头的矩阵,某些位置待填,问最多有多少位置满足从这个位置开始沿箭头方向移动走不出矩阵。

BFS搜索一定能走出去的位置,没填的位置一定能走出去当且仅当它的四周全是能走出去的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1005;
int n,m;
string a[N];
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
const char de[4]={'U','L','D','R'};
bool vis[N][N];
void solve(){
cin>>n>>m;
for(int i=0;i<n;++i)cin>>a[i];
if(n==1&&m==1){
cout<<"0\n";
return;
}
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
vis[i][j]=0;
queue<pii> q;
for(int i=0;i<n;++i){
if(a[i][0]=='L')q.push(pii(i,0));
if(a[i][m-1]=='R')q.push(pii(i,m-1));
}
for(int i=0;i<m;++i){
if(a[0][i]=='U')q.push(pii(0,i));
if(a[n-1][i]=='D')q.push(pii(n-1,i));
}
while(!q.empty()){
int x=q.front().first,y=q.front().second;
q.pop();
vis[x][y]=1;
for(int i=0;i<4;++i){
int xx=x+dx[i],yy=y+dy[i];
if(xx<0||xx>=n||yy<0||yy>=m||a[xx][yy]=='?')continue;
if(a[xx][yy]==de[i])q.push(pii(xx,yy));
}
}
int ans=0;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j){
if(a[i][j]!='?'){
if(!vis[i][j])++ans;
}
else{
bool fl=0;
for(int t=0;t<4;++t){
int ii=i+dx[t],jj=j+dy[t];
if(ii>=0&&ii<n&&jj>=0&&jj<m&&!vis[ii][jj]){fl=1;break;}
}
if(fl)++ans;
}
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

D. Darius' Wisdom

题意:n 堆石子,每堆石子数量不超过 2。每次只能交换两堆石子数差 1 的石子,给出一种操作数不超过 n 的方案使所有石子从小到大排序。

先把所有的 1 归位,然后用任意一个 1 把 0 和 2 归位。具体见代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5;
int n,a[N],c[3];
vector<pii> ans;
vector<int> b[3][3];
int pos(int x){
if(x>=1&&x<=c[0])return 0;
else if(x>=c[0]+1&&x<=c[0]+c[1])return 1;
else return 2;
}
void mov(int i1,int j1,int i2,int j2){
int x=b[i1][j1].back(),y=b[i2][j2].back();
ans.emplace_back(x,y);
b[i1][j1].pop_back();
b[i1-1][j1].push_back(x);
b[i2][j2].pop_back();
b[i2+1][j2].push_back(y);
}
void solve(){
cin>>n;
c[0]=c[1]=c[2]=0;
for(int i=1;i<=n;++i)cin>>a[i],++c[a[i]];
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
b[i][j].clear();
for(int i=1;i<=n;++i)b[a[i]][pos(i)].push_back(i);
ans.clear();
while(b[0][1].size()||b[0][2].size()||b[1][0].size()||b[1][2].size()||b[2][0].size()||b[2][1].size()){
int st=ans.size();
while(b[2][0].size()&&b[1][2].size())mov(2,0,1,2);
while(b[2][1].size()&&b[1][2].size())mov(2,1,1,2);
while(b[1][0].size()&&b[0][2].size())mov(1,0,0,2);
while(b[1][0].size()&&b[0][1].size())mov(1,0,0,1);
if(ans.size()==st)break;
}
if(b[2][0].size()){
int t=b[1][1].back(),m=b[2][0].size();
ans.emplace_back(b[2][0][0],t);
ans.emplace_back(b[2][0][0],b[0][2][0]);
for(int i=1;i<m;++i){
ans.emplace_back(b[2][0][i],b[0][2][i-1]);
ans.emplace_back(b[2][0][i],b[0][2][i]);
}
ans.emplace_back(t,b[0][2][m-1]);
}
cout<<ans.size()<<'\n';
for(auto&[x,y]:ans)cout<<x<<' '<<y<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

E. Permutations Harmony

题意:给 n,k,构造 k 个不同的排列 p1,,pk,使得对所有的 ji=1kpi,j 相等。

n 为偶数,k 为奇数时,因为 nkn(n+1)2,所以无解;

k=1,k=n!1,k>n! 时,无解;

其他情况均有解,分 k 为奇数和偶数讨论。

  • k 为偶数时:12345 54321 12354 54312……从小到大枚举排列配上 n+1 减每一项的排列即可。

  • k 为奇数时:我们先构造出一组 k=3 的。第一个排列从小到大,第二个排列奇数项从 n+12 开始递减、偶数项从 n 开始递减。以 n=7 为例:1234567 4736251 7362514。剩下的和 k 为偶数一样,碰到重复的跳过即可。这样恰好可以把 k3n!3 的所有情况都构造出来。

注意特判 n=k=1

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5;
const int fac[9]={1,1,2,6,24,120,720,5040,40320};
int n,k,p[N],q[N],r[N];
void solve(){
cin>>n>>k;
if(k==1){
if(n==1)cout<<"YES\n1\n";
else cout<<"NO\n";
}
else if(n<=8&&k>fac[n])cout<<"NO\n";
else if(!(n&1)&&(k&1))cout<<"NO\n";
else if(n<=8&&k==fac[n]-1)cout<<"NO\n";
else{
cout<<"YES\n";
for(int i=1;i<=n;++i)p[i]=i;
if(!(k&1)){
for(int i=1;i<=k;i+=2){
for(int i=1;i<=n;++i)cout<<p[i]<<' ';
cout<<'\n';
for(int i=1;i<=n;++i)cout<<n-p[i]+1<<' ';
cout<<'\n';
next_permutation(p+1,p+n+1);
}
}
else{
for(int i=1;i<=n/2;++i)q[i*2-1]=n/2+2-i,q[i*2]=n+1-i;
q[n]=1;
for(int i=1;i<=n/2;++i)r[i*2]=n/2+1-i,r[i*2+1]=n-i;
r[1]=n;
for(int i=1;i<=n;++i)cout<<p[i]<<' ';
cout<<'\n';
for(int i=1;i<=n;++i)cout<<q[i]<<' ';
cout<<'\n';
for(int i=1;i<=n;++i)cout<<r[i]<<' ';
cout<<'\n';
for(int i=4;i<=k;i+=2){
bool fl1=1,fl2=1,fl3=1,fl4=1,fl5=1,fl6=1;
for(int i=1;i<=n;++i){
if(p[i]!=i)fl1=0;
if(p[i]!=q[i])fl2=0;
if(p[i]!=r[1])fl3=0;
if(n-p[i]+1!=i)fl4=0;
if(n-p[i]+1!=q[i])fl5=0;
if(n-p[i]+1!=r[i])fl6=0;
}
if(!fl1&&!fl2&&!fl3&&!fl4&&!fl5&&!fl6){
for(int i=1;i<=n;++i)cout<<p[i]<<' ';
cout<<'\n';
for(int i=1;i<=n;++i)cout<<n-p[i]+1<<' ';
cout<<'\n';
}
else i-=2;
next_permutation(p+1,p+n+1);
}
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

F1. Khayyam's Royal Decree (Easy Version)

题意:有 n 个红球和 m 个蓝球,每次等概率取一个,取到红球得 2 分,取到蓝球得 1 分。另有 k 个检查点,当红球数恰好为 ri 且蓝球数恰好为 bi 时分数乘 2。求期望得分。

我们首先把期望转化成计数,即对所有取球方案求得分之和。最后再除 (n+mn) 即可。

检查点可以拓扑排序。设 fi 表示到达第 i 个检查点的所有方案的得分之和,pi,j 表示从第 i 个检查点到第 j 个检查点且中间不经过任何其他检查点的方案数,则有

pi,j=si,jk=i+1j1pi,ksk,j,fi=j=0i1(2fj+s0,jwj,i)pj,i

其中 si,j 表示从 ij 的总方案数,wi,j 表示从 ij 的得分。

总复杂度 O(n3)。如果能快速转移或计算 p 应该能做 F2(?

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4e5+5,K=505,mod=998244353;
ll fac[N],inf[N];
void init(int n){
fac[0]=1;
for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%mod;
inf[1]=1;
for(int i=2;i<=n;++i)inf[i]=inf[mod%i]*(mod-mod/i)%mod;
inf[0]=1;
for(int i=1;i<=n;++i)inf[i]=inf[i-1]*inf[i]%mod;
}
ll C(int n,int m){
return fac[n]*inf[m]%mod*inf[n-m]%mod;
}
int n,m,k,r[K],b[K],d[K];
ll P(int i,int j){
return C(r[j]-r[i]+b[j]-b[i],r[j]-r[i]);
}
bool e[K][K];
vector<int> E[K],G[K];
ll p[K][K],f[K];
queue<int> q;
vector<int> o;
void solve(){
cin>>n>>m>>k;
for(int i=1;i<=k;++i)cin>>r[i]>>b[i],r[i]=n-r[i],b[i]=m-b[i];
r[++k]=n,b[k]=m;
for(int i=0;i<=k;++i)E[i].clear(),G[i].clear(),d[i]=0,memset(e[i],0,sizeof(bool)*(k+1));
for(int i=0;i<=k;++i)
for(int j=0;j<=k;++j)
if(i!=j&&r[i]<=r[j]&&b[i]<=b[j])
e[i][j]=1,E[i].push_back(j),G[j].push_back(i),++d[j];
o.clear();
for(int i=0;i<=k;++i)if(!d[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
o.push_back(u);
for(int v:E[u])if(!--d[v])q.push(v);
}
memset(f,0,sizeof(ll)*(k+1));
for(int i=0;i<=k;++i){
for(int j=i+1;j<=k;++j)if(e[o[i]][o[j]]){
p[o[i]][o[j]]=P(o[i],o[j]);
for(int t:G[o[j]])if(e[o[i]][t])p[o[i]][o[j]]=(p[o[i]][o[j]]-p[o[i]][t]*P(t,o[j])%mod+mod)%mod;
f[o[j]]=(f[o[j]]+(2*f[o[i]]+(2*(r[o[j]]-r[o[i]])+(b[o[j]]-b[o[i]]))*P(0,o[i])%mod)*p[o[i]][o[j]])%mod;
}
}
cout<<f[k]*inf[n+m]%mod*fac[n]%mod*fac[m]%mod<<'\n';
}
int main(){
init(4e5);
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
posted @   EssnSlaryt  阅读(146)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示