Codeforces Round 889 (Div. 2) A-D
A. Dalton the Teacher
题意:给出一个排列,问使得排列变为1,2,...,n的最小的交换操作次数
Solution
统计a[i]!=i的个数,答案就是除以二向上取整
void solve()
{
int n;cin>>n;
int res=0;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
if(x==i)res++;
}
cout<<(res+1)/2<<"\n";
}
B. Longest Divisors Interval
题意:给出一个数,求出最长的区间的长度,使得区间中的每个数都是这个数的因数
Solution
从1开始找,直到找到不是因数的,假设[l,r]都是是n的因数,那么显然[1,r/l]也是
void solve()
{
int n;cin>>n;
int res=0;
for(int i=1;i<=n;i++)
{
if(n%i==0)res++;
else break;
}
cout<<res<<"\n";
}
C. Dual
题意:给出一个数组a,可以进行最多31次操作,每次操作可以选两个数i,j,并进行a[i]+=a[j],构造一个操作序列,使得数组变为不降序列
Solution
统计大于0的数和小于0的数的个数,如果都为0则无需操作,如果其中一个为0则进行一趟前缀和/后缀和即可
如果都不为0,则考虑两种操作,分别是把大于0的都变为小于0的然后再后缀和,或是把小于0的都变为大于0的,再进行前缀和
都跑一遍然后对两种操作次数取小
int a[25];
int b[25];
int mx[25];
int mi[25];
void solve()
{
int n;cin>>n;
vector<pii>ans;
int pos=0;
int cnt0=0,cnt1=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(i==1)mx[i]=mi[i]=a[i];
else
{
mx[i]=max(mx[i-1],a[i]);
mi[i]=min(mi[i-1],a[i]);
}
if(a[i]>0)cnt1++;
else if(a[i]<0) cnt0++;
}
if(mx[n]==0&&mi[n]==0)
{
cout<<"0\n";
return;
}
if(cnt0==0)
{
for(int i=2;i<=n;i++)
{
while(a[i]<a[i-1])
{
a[i]+=a[i-1];
ans.push_back({i,i-1});
}
}
cout<<ans.size()<<"\n";
for(auto it:ans)
{
cout<<it.first<<" "<<it.second<<"\n";
}
}else if(cnt1==0)
{
for(int i=n-1;i>=1;i--)
{
while(a[i]>a[i+1])
{
a[i]+=a[i+1];
ans.push_back({i,i+1});
}
}
cout<<ans.size()<<"\n";
for(auto it:ans)
{
cout<<it.first<<" "<<it.second<<"\n";
}
}
else
{
for(int i=1;i<=n;i++)b[i]=a[i];
vector<pii>ans1;
vector<pii>ans2;
for(int i=1;i<=n;i++)
{
if(b[i]==mx[n])
{
pos=i;
break;
}
}
while(abs(b[pos])<abs(mi[n]))
{
b[pos]+=b[pos];
ans1.push_back({pos,pos});
}
for(int i=1;i<=n;i++)
{
if(b[i]<0)
{
ans1.push_back({i,pos});
}
}
for(int i=2;i<=n;i++)ans1.push_back({i,i-1});
for(int i=1;i<=n;i++)b[i]=a[i];
for(int i=1;i<=n;i++)
{
if(b[i]==mi[n])
{
pos=i;
break;
}
}
while(abs(b[pos])<abs(mx[n]))
{
b[pos]+=b[pos];
ans2.push_back({pos,pos});
}
for(int i=1;i<=n;i++)
{
if(b[i]>0)
{
ans2.push_back({i,pos});
}
}
for(int i=n-1;i>=1;i--)ans2.push_back({i,i+1});
if(ans1.size()>ans2.size())
{
cout<<ans2.size()<<"\n";
for(auto it:ans2)cout<<it.first<<" "<<it.second<<"\n";
}else
{
cout<<ans1.size()<<"\n";
for(auto it:ans1)cout<<it.first<<" "<<it.second<<"\n";
}
}
}
D. Earn or Unlock
题意:给出n张牌,最开始只有第一张牌是解锁状态,其它牌都被锁住了,每张牌上有一个点数a[i],每次可以进行一种操作:
1.解锁顶上的未解锁的a[i]张牌
2.获得a[i]的胜利点数
问最后能得到的最大点数是多少
Solution
定义
void solve()
{
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+a[i];
}
bitset<200005>dp;
dp[1]=1;
int ans=0;
for(int i=1;i<=n;i++)
{
dp|=dp<<a[i];
if(dp[i])
{
ans=max(ans,s[i]-i+1);
dp[i]=0;
}
}
// cout<<dp<<"\n";
for(int i=n+1;i<=2*n;i++)
{
if(dp[i])
{
ans=max(ans,s[n]-i+1);
dp[i]=0;
}
}
cout<<ans<<"\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现