P6187 [NOI Online #1 提高组] 最小环
题目大意
给定一个长度为 的正整数序列 ,下标从 开始编号。我们将该序列视为一个首尾相邻的环,更具体地,对于下标为 , 的两个数 , ,它们的距离为 。
现在再给定 个整数 , ,..., ,对每个 (, ,..., ),你需要将上面的序列 重新排列,使得环上任意两个距离为 的数字的乘积之和最大。
思路
-
如果则一定会形成多个部分
-
当时,显然应该大的挨着大的,以最大的为中心,向两侧依次减少。
-
当且时,我们考虑将时的代价断开,每一段长,一共有段。
例如: 6 5 4 3 2 1 在k=1时为:6×5 6×4 5×3 4×2 3×1 1×2 在k=2时为:6×5 6×4 5×4 3×2 2×1 3×1 不难发现,若在i和i+1处断开,则对答案的贡献为 -(a[i]*a[i+2]+a[i-1]*a[i+1])+(a[i]*a[i-1]+a[i+1]*a[i+2])
- 预处理出来,然后乱搞即可
代码
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<stack> #include<vector> #include<iomanip> #define LL long long #define N 200010 using namespace std; LL n,m,a[N],ans[N]; LL read(){ LL x=0,h=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+(LL)(ch-'0');ch=getchar();} return x*h; } LL gcd(LL a,LL b){ return b==0 ? a:gcd(b,a%b); } void gans(LL k){ LL jp=n/k; ans[k]=ans[1]; for(LL i=n-jp;i;i-=jp){ ans[k]-=(a[i+2]*a[i]+a[i-1]*a[i+1]); ans[k]+=(a[i]*a[i-1]+a[i+1]*a[i+2]); } return ; } void solve(){ // solve q=0 for(LL i=1;i<=n;i++){ ans[0]+=(a[i]*a[i]); } // solve q=1 ans[1]+=a[n]*a[n-1]; for(LL i=n;i>2;i-=2){ ans[1]+=a[i]*a[i-2]; } for(LL i=n-1;i>2;i-=2){ ans[1]+=a[i]*a[i-2]; } ans[1]+=a[1]*a[2]; // solve other for(LL i=2;i<=sqrt(n);i++){ if(n%i!=0)continue; // solve i gans(i); // solve n/i if(n/i<=n/2)gans(n/i); } } int main(){ n=read(); m=read(); for(LL i=1;i<=n;i++)a[i]=read(); sort(a+1,a+n+1); solve(); for(LL i=1;i<=m;i++){ LL x=read(); //注意特判!!! if(n==1){ printf("%lld\n",a[1]*a[1]); continue; } if(x==0)printf("%lld\n",ans[0]); else printf("%lld\n",ans[gcd(x,n)]); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现