2024.12.19 Codeforces Global Round 28

比赛连接


Solved: 6/10


A. Kevin and Combination Lock

题意:给一个整数,每次你可以将它减 33 或擦掉一个 33,问能否变成 0。

注意到擦掉 33 不会改变原数模 3 和 11 的余数,因此只需判断原数能否被 33 整除。

#include<bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin>>n;
cout<<(n%33?"NO":"YES")<<'\n';
}
int main(){
int T;
cin>>T;
while(T--)solve();
}

B. Kevin and Permutation

题意:构造一个排列 p,使得 i=1nk+1minj=1j+k1pj 最小。

每隔 k 个位置放尽量小的数即可。

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

C. Kevin and Binary Strings

题意:给一个 01 串,找出两个子串使得它们的异或和最大。|s|5000

因为位数越多越大,所以其中一个子串必为整个串。而另一个串需要高位尽可能是 1。原串的前几个 1 显然可以保留,找到从高位开始第一个 0 的位置,从这一位开始的长度就是第二个串的长度。因为 n2 可过,所以直接枚举第二个串的起始位置即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
string a;
cin>>a;
int n=a.length(),pos=-1;
for(int i=0;i<n;++i)a[i]-='0';
for(int i=0;i<n;++i)if(!a[i]){pos=i;break;}
if(pos==-1){cout<<1<<' '<<n<<' '<<1<<' '<<1<<'\n';return;}
string mx="";
int ans=0;
for(int j=0;j<pos;++j){
string s=a;
for(int k=0;k<n-pos;++k)s[pos+k]^=a[j+k];
if(s>mx)mx=s,ans=j;
}
cout<<1<<' '<<n<<' '<<ans+1<<' '<<ans+n-pos<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

D. Kevin and Competition Memories

题意:n 个人,第 i 个人水平为 aim 道题,第 j 道题难度为 bj。每个人能做出且仅能做出 bjai 的题。
每场比赛 k 道题,举办 mk 场比赛,每道题只能供一场比赛。n,m3×105
对每个 k,求所有比赛第 1 个人排名之和的最小值。

考虑每个人对答案的贡献。设满足 a1<bjaij 共有 ti 个,则

ansk=mk+i=2ntik+[timodk>mmodk]=mk+i=2nmkmtik.

ti 可以排序后双指针求,处理贡献时可用整除分块+差分数组优化为 O(m)。总复杂度 O(nm)

好像有点卡常(赛时提交 1900+ms)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()
void solve(){
int n,m;
cin>>n>>m;
vector<int> a(n),b(m);
for(int& x:a)cin>>x;
for(int& x:b)cin>>x;
int a0=a[0];
sort(all(a)),sort(all(b));
int cnt=0,p=n,q=m;
for(int i=0;i<n;++i)if(a[i]>a0){p=i;break;}
for(int i=0;i<m;++i)if(b[i]>a0){q=i;break;}
vector<ll> s(m+2);
for(int i=p,j=q;i<n;++i){
while(j<m&&b[j]<=a[i])++j;
int t=m-(j-q);
for(int l=1,r;l<=t;l=r+1){
r=t/(t/l);
s[l]-=t/l,s[r+1]+=t/l;
}
}
for(int i=1;i<=m;++i)s[i]+=s[i-1];
for(int i=1;i<=m;++i)s[i]+=1ll*(n-p+1)*(m/i),cout<<s[i]<<' ';
cout<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

E. Kevin and Bipartite Graph

题意:完全二分图 K(2n,m),给每条边染色为 n 种颜色,给出染色方案使得不存在同色环。

纯试出来的构造,不知道有没有更简洁的方法。

2nm 无解,直接输出 NO。

n=4 为例:

1 1 2 3 4 2 3 4
2 2 3 4 1 3 4 1
3 3 4 1 2 4 1 2
4 4 1 2 3 1 2 3
1 2 3 4 1 2 3 4
2 3 4 1 2 3 4 1
3 4 1 2 3 4 1 2
4 1 2 3 4 1 2 3

取前 m 列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()
void solve(){
int n,m;
cin>>n>>m;
if(n*2<=m){
cout<<"NO\n";
return;
}
vector<vector<int>> a(2*n);
for(int i=0;i<2*n;++i)a[i].resize(2*n);
for(int i=0;i<n;++i){
a[i][0]=a[i][1]=i;
for(int j=0;j<n;++j)a[n+i][j]=a[n+i][n+j]=(i+j)%n;
for(int j=1;j<n;++j)a[i][j+1]=a[i][j+n]=(i+j)%n;
}
cout<<"YES\n";
for(int i=0;i<n*2;++i,cout<<'\n')
for(int j=0;j<m;++j)
cout<<a[i][j]+1<<' ';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}

F. Kevin and Math Class

题意:给两个序列 ab。每次操作可以选择一个区间 [l,r],令 x=minj=lrbj,然后对每个 liraiaix。问最少几次操作可使序列 a 全为 1n2×105,ai1018

容易发现

  • 总操作数不超过 logw60
  • 操作顺序一定是从小区间到大区间,除的数从大到小。

b 序列建立笛卡尔树,设 f(u,k) 表示以 u 为顶点的子树共操作 k 次最大值的最小值。则有转移

f(u,i+j+k)max{au,f(lcu,i),f(rcu,j)}buk.

分两步转移,总复杂度 O(nlog2w)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()
const int N=2e5+5;
int n;
ll a[N],b[N];
int st[20][N];
int mini(int i,int j){
return b[i]<=b[j]?i:j;
}
int qmni(int l,int r){
int o=__lg(r-l+1);
return mini(st[o][l],st[o][r-(1<<o)+1]);
}
ll f[N][60];
int rt,lc[N],rc[N];
int bld(int l,int r){
int mid=qmni(l,r);
lc[mid]=mid>l?bld(l,mid-1):0;
rc[mid]=mid<r?bld(mid+1,r):0;
return mid;
}
void dfs(int u){
if(lc[u])dfs(lc[u]);
if(rc[u])dfs(rc[u]);
memset(f[u],0x3f,sizeof(ll)*60);
for(int i=0;i<60;++i)
for(int j=0;i+j<60;++j)
f[u][i+j]=min(f[u][i+j],max(a[u],max(f[lc[u]][i],f[rc[u]][j])));
ll g[60];
memset(g,0x3f,sizeof(ll)*60);
for(int i=0;i<60;++i){
ll t=f[u][i];
for(int j=0;i+j<60;++j)
g[i+j]=min(g[i+j],t),t=(t+b[u]-1)/b[u];
}
memcpy(f[u],g,sizeof(ll)*60);
}
void solve(){
cin>>n;
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=n;++i)cin>>b[i],st[0][i]=i;
for(int i=1;1<<i<=n;++i)
for(int j=1;j+(1<<i)-1<=n;++j)
st[i][j]=mini(st[i-1][j],st[i-1][j+(1<<i-1)]);
rt=bld(1,n);
dfs(rt);
for(int i=0;i<60;++i)if(f[rt][i]==1){cout<<i<<'\n';return;}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
posted @   EssnSlaryt  阅读(362)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示