51nod 石子分配
可以发现步数限制把数轴变为了环。环之间不可以交换,环内相邻两点可以交换,然后我们只需要对每个环操作,最后累加。
对于环上的每个石子堆,我们需要将其石子数调整到均值 \(avg\)。因此,我们首先计算每个堆石子相对于 \(avg\) 的偏差,即 \(nowa[i] - avg\)。
因为相邻节点不一定能凑齐 \(avg\),所以我们用 \(b[]\) 数组累积偏差,累积这些偏差后,我们需要选择一个调整量,使得调整所需的总代价最小,那这个数肯定是中位数啊,所以我们环上的每个 \(b[i]\) 都减去中位数然后累加就是这个环的总的操作次数了。
完整代码有注释:
#include<bits/stdc++.h> using namespace std; #define ll long long int n,k; ll ans; ll avg;//平均值 ll b[50010];//记录累积偏差值 int nowa[50010];//这个环的第几的点 int a[50010];//这堆石头数 bool vis[50010];//判断这个点是否在环内 ll get_ans(int x){ int t=0; while(!vis[x]){//已经在环中了 vis[x]=1; nowa[++t]=a[x]; x+=k; if(x>n){ x-=n; } } b[1]=0; for(int i=2;i<=t;i++){ b[i]=b[i-1]+(nowa[i-1]-avg);//累计偏移量 } sort(b+1,b+1+t); ll s1=b[(t+1)/2];//取中位数 ll nowans=0; for(int i=1;i<=t;i++){ nowans+=abs(b[i]-s1);//取最小操作数 } return nowans; } int main() { ios::sync_with_stdio(false); cin>>n>>k; k++; for(int i=1;i<=n;i++){ cin>>a[i]; avg+=a[i]; } avg/=n; for(int i=1;i<=n;i++){ if(vis[i]){//已经在环中了 continue; } ans+=get_ans(i); } cout<<ans; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」