Codeforces Round #601 (Div. 1) A-B2 题解
本文网址:https://www.cnblogs.com/zsc985246/p/17096620.html ,转载请注明出处。
传送门
Codeforces Round #601 (Div. 1)
A. Feeding Chicken
题目大意
有一个 的网格,上面的每个数是 或 。求一种将网格划分为 个连通块的方案,使得块中 的个数极差最小。
。
思路
蛇形遍历整个网格可以保证连通性,块内的 的个数可以提前计算,直接模拟即可。
代码实现
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(ll i=(a);i<=(b);++i)
#define Rep(i,a,b) for(ll i=(a);i>=(b);--i)
const ll N=100+10;
using namespace std;
ll n,m,k;
ll a[N][N];
char b[N][N];//答案数组
//题目要求的神奇输出格式
char c[111]={'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
void mian(){
ll cnt=0;
ll s=0;//1的总数
scanf("%lld",&n);
scanf("%lld",&m);
scanf("%lld",&k);
For(i,1,n){
char str[111];
scanf("%s",str+1);
For(j,1,m){
if(str[j]=='R')a[i][j]=1;
else a[i][j]=0;
s+=a[i][j];
}
}
ll tot=s/k;//每个连通块1的个数
ll id=k-s+tot*k;//大于等于它的编号都需要多分一个1
ll now=0;//已经划分的1的个数
For(x,1,n){
if(x&1){
For(y,1,m){
now+=a[x][y];
b[x][y]=c[cnt];
if(now==tot+(cnt>=id)&&cnt<k-1){//注意不要分多了,保证cnt<=k
cnt++;
now=0;
}
}
}else{
Rep(y,m,1){
now+=a[x][y];
b[x][y]=c[cnt];
if(now==tot+(cnt>=id)&&cnt<k-1){
cnt++;
now=0;
}
}
}
}
For(i,1,n){
For(j,1,m){
putchar(b[i][j]);
}
printf("\n");
}
}
int main(){
int T=1;
scanf("%d",&T);
while(T--)mian();
return 0;
}
B. Send Boxes to Alice
题目大意
有 个盒子,分别放了 个物品。一次操作可以将一个物品移到相邻的盒子里。求使所有非空盒子物品数的最小公约数不为 的最小操作次数。
在 Easy Version 中,。
在 Hard Version 中,。
思路
对于 B1,发现 只有可能是 或 。
当然,如果 的个数少于 ,肯定无解。
考虑直接枚举它们的最小公约数 ,然后将每 个 移动到一起。
可以发现,最终每一组都会移到最中间的 的位置。(将 看成数轴上的点,抽象成中位数定理的模型)
这样 B1 就做完了。
对于 B2,我们发现还是可以枚举它们的最小公约数 ,但是我们计算答案的方式需要改变。
考虑将数组作前缀和。可以发现,一次操作就变为了将前缀和数组中的一个数 或 。当然盒子中物品的数量不可能是负数,所以还需要保证 数组单调递增。
也就是说,我们最后需要使每个 都是 的倍数。
我们发现,当 数组具有单调性时,如果让每个 变成离它最近的 的倍数,形成的新数组同样满足单调性。同时,由于我们让它成为了最近的倍数,所以一定保证操作数最小。
这样 B2 就搞定了。
代码实现
这里就放 B2 的代码好了。
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(ll i=(a);i<=(b);++i)
#define Rep(i,a,b) for(ll i=(a);i>=(b);--i)
const ll N=1e6+10;
using namespace std;
ll n,m,k;
ll a[N];
ll s[N];
ll calc(ll x){//计算答案
ll res=0;
For(i,1,n){
res+=min(s[i]%x,x-s[i]%x);//离它最近的倍数
}
return res;
}
void mian(){
ll ans=5e18;//开大一点,在B1中最大是3e9,B2中是3e16
scanf("%lld",&n);
For(i,1,n){
scanf("%lld",&a[i]);
s[i]=s[i-1]+a[i];//前缀和
}
if(s[n]<=1){//总共不到2个物品
printf("-1\n");
return;
}
ll t=s[n];
for(ll i=2;i*i<=t;++i){
if(t%i==0){
while(t%i==0)t/=i;
ans=min(ans,calc(i));
}
}
if(t!=1){
ans=min(ans,calc(t));
}
printf("%lld\n",ans);
}
int main(){
int T=1;
// scanf("%d",&T);
while(T--)mian();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!