CF1416B Make Them Equal 题解
CF1416B Make Them Equal
- 给出一个序列 \(a\),求出一个长度不超过 \(3n\) 的操作序列,使序列 \(a\) 中每个元素相等。
- 定义一次操作为:选出 \((i,j,x)\) 三元组,满足 \(i,j\) 为序列合法下标,\(x\) 为 \(10^9\) 以内非负整数,令 \(a_i:= a_i-x\cdot i,a_j:=a_j+x\cdot i\)。
- 必须保证操作过程中的任意时刻序列 \(a\) 中每个元素都非负。
- 输出时先输出操作次数 \(k\),然后输出 \(k\) 行操作序列。
- 数据组数 \(t\le10^4\),序列长度 \(n\le10^4\),元素大小 \(1\le a_i\le10^5\),保证初始时 \(1\leq a_i\leq 10^5\)。
容易发现两次操作之后整个序列之和不变,所以如果 \(n\nmid \sum a_i\),那么无解。
一个思路时将所有的数加到位置 \(1\) 上,然后位置 \(1\) 可以将这些数均分后加到各个位置上。
但是如果一个位置 \(i\nmid a_i\),那么无法一次将所有数转移过来。
考虑到一开始 \(a_i\geq 1\),所以如果 \(a_2\bmod 2=1\),则可以执行操作 \((1,2,1)\),使得 \(2\mid a_2\)。接着执行 \((2,1,a_2/2)\)。又 \(a_2\geq 1\),于是我们在执行操作 \((i,1,a_{i}/{i})\) 之后,\(a_i\geq i\),所以如果 \(i+1\nmid a_{i+1}\),那么必然可以通过执行 \((1,i+1,x)\) 操作使得 \((i+1)\nmid a_{i+1}\),其中 \(x\leq i\)。
具体见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int>ttfa;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1000006;
int n;ll a[N];
inline void Tesc(){
n=read();ll s=0;
for(int i=1;i<=n;++i){
a[i]=read();
s+=a[i];
}
if(s%n)return puts("-1"),void();
printf("%d\n",3*(n-1));
for(int i=2;i<=n;++i){
ll res=(i-a[i]%i)%i;
printf("%d %d %lld\n",1,i,res);
a[i]+=res;a[1]-=res;
res=a[i]/i;
a[i]-=res*i,a[1]+=res*i;
printf("%d %d %lld\n",i,1,res);
}
s/=n;
for(int i=2;i<=n;++i)
printf("%d %d %lld\n",1,i,s);
}
int main(){
int T=read();
while(T--)Tesc();
return 0;
}
本文作者:BigSmall_En
本文链接:https://www.cnblogs.com/BigSmall-En/p/16823069.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
,
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步