CF-Codeforces Round #673 (Div. 2)-1417D. Make Them Equal【思维】

题目链接
题意:给定一序列 { a 1 , a 2 , a 3 , . . . , a n } \{a_1,a_2,a_3,...,a_n\} {a1,a2,a3,...,an},和如下操作:

  • 选择两个元素 a i , a j a_i,a_j ai,aj和一整数 x x x,令 a i = a i + x ∗ i , a j = a j − x ∗ i a_i=a_i+x*i,a_j=a_j-x*i ai=ai+xi,aj=ajxi

问能否在不超过 3 n 3n 3n次操作内,使得序列所有元素相同
思路:为了方便表述,将操作选择的数是 i , j , x i,j,x i,j,x时记作操作 [ i , j , x ] [i,j,x] [i,j,x]
明显序列的和是不变的,所以可以求出序列的平均数 a v e ave ave,如果 a v e ave ave不是整数,则不可能完成,输出-1即可;对于其它情况,我们考虑如下操作:

  1. a 2 , a 3 , . . . , a n a_2,a_3,...,a_n a2,a3,...,an都加到 a 1 a_1 a1上,当 a i % i = 0 a_i\%i=0 ai%i=0 ( i = 2 , 3 , . . . , n ) (i=2,3,...,n) (i=2,3,...,n)时直接令操作为 [ i , 1 , a i / i ] [i,1,a_i/i] [i,1,ai/i],否则先令操作为 [ 1 , i , i − a i % i ] [1,i,i-a_i\%i] [1,i,iai%i],由于我们是从 a 2 a_2 a2开始顺序往后遍历,简单思考一下就可以发现过程中是可以保证 a 1 a_1 a1非负的。这一部分操作数不超过 2 ( n − 1 ) 2(n-1) 2(n1)
  2. a 1 a_1 a1平分到 a 2 , a 3 , . . . , a n a_2,a_3,...,a_n a2,a3,...,an,这一过程操作数是 n − 1 n-1 n1
    故以上操作后,可以在不超过 3 n 3n 3n次操作内使得所有元素相同。
    AC代码:
#include <bits/stdc++.h>
#define pcc pair<char, char>
#define pii pair<int, int>
#define vi vector<int>
#define vl vector<ll>
#define rep(i, x, y) for (int i = x; i < y; i++)
#define per(i, x, y) for (int i = x; i >= y; i--)
#define rep0(i, n) for (int i = 0; i < (n); i++)
#define per0(i, n) for (int i = (n)-1; i >= 0; i--)
#define mp make_pair
#define pb push_back
#define F first
#define S second
#define sz(x) (x).size()
#define all(x) (x).begin(), (x).end()
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
using namespace std;

inline int read() {
 int x = 0, f = 1;
 char ch = getchar();
 while (ch < '0' || ch > '9') {
   if (ch == '-') f = -1;
   ch = getchar();
 }
 while (ch >= '0' && ch <= '9') {
   x = x * 10 + ch - '0';
   ch = getchar();
 }
 return x * f;
}

const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e4 + 10;
const int MAX = 1e5;
const double pi = acos(-1.0);
const ll INF = 0x3f3f3f3f3f3f3f;
/***************main****************/
ll T = 1;
ll m, n;
ll a[maxn];
vector<ll> I, J, X;
int main() {
 // freopen("1.txt", "r", stdin);
 T = read();
 while (T--) {
   cin >> n;
   ll sum = 0, cnt = 0;
   I.clear(), J.clear(), X.clear();
   rep(i, 1, n + 1) {
     a[i] = read();
     sum += a[i];
   }
   if (sum != n * (sum / n)) {
     cout << -1 << endl;
     continue;
   }
   ll ave = sum / n;
   rep(i, 2, n + 1) {  //第一部分操作,不超过2*(n-1)
     if (a[i] % i) {
       ll x = i - a[i] % i;
       X.push_back(x);
       I.push_back(1);
       J.push_back(i);
       a[i] += x;
       a[1] -= x;
       cnt++;
     }
     I.push_back(i);
     J.push_back(1);
     X.push_back(a[i] / i);
     cnt++;
   }
   rep(i, 2, n + 1) {  //第二部分操作,n-1次
     I.push_back(1);
     J.push_back(i);
     X.push_back(ave);
     cnt++;
   }
   cout << cnt << endl;
   rep(i, 0, cnt) { cout << I[i] << ' ' << J[i] << ' ' << X[i] << '\n'; }
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值