Gushing over Programming Girls|

BigSmall_En

园龄:3年2个月粉丝:3关注:5

2022-10-24 21:22阅读: 20评论: 0推荐: 0

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 中国大陆许可协议进行许可。

posted @   BigSmall_En  阅读(20)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起