codeforces#673 D. Make Them Equal[构造]

题目大意:给一个长为n的数组,一次操作是指选择i,j,x,使a[i]=a[i]-i*x,a[j]=a[j]+i*x,问能否在3*n次内通过操作使整个数组为同一个数字

思路: 通过 a[i]=a[i]-i*x,a[j]=a[j]+i*x 可知数组的总和是不会改变的,那么最后数组里的数字一定是平均数,如果平均数不为整数,说明无解,输出-1

构造:1.使a[2]~a[n]的数字全都成为i的倍数

   2.全都加进a[1]中

   3.由a[1]对各个数字进行分配

可行性证明:由于总和不会改变,所以操作2进行完之后a[1]为总和,其余全都为0,那么对于每个i进行操作(1 , i , sum/n)即可

代码:

 1 #include<bits/stdc++.h>
 2 #define fi first
 3 #define se second
 4 #define pb(i) push_back(i)
 5 #define rep(i,a,b) for(int i=a;i<=b;i++)
 6 #define per(i,a,b) for(int i=b;i>=a;i--)
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define VI vector<int>
 9 #define VLL vector<ll>
10 #define MPII map<pair<int,int>,int>
11 #define mp make_pair
12 #define PQI priority_queue<int>
13 #define debug(a) cout<<#a<<'='<<a<<'\n'
14 using namespace std;
15 typedef long long ll;
16 typedef unsigned long long ull;
17 const int N = 2e4+10;
18 const int INF = 0x3f3f3f3f;
19 const int inf = - INF;
20 const int mod = 1e9+7;
21 const double pi = acos(-1.0);
22 const double eps=1e-5;
23 #define sc(x) scanf("%d",&x);
24 #define scll(x) scanf("%lld",&x);
25 ll a[N];
26 void op(int i,int j,ll x){
27     a[i]-=i*x;
28     a[j]+=i*x;
29     printf("%d %d %lld\n",i,j,x);
30 }
31 int main(){
32     int T;sc(T);
33     while(T--){
34         int n;sc(n);
35         ll sum=0;
36         for(int i=1;i<=n;i++){
37             scll(a[i]);
38             sum+=a[i];
39         }
40         ll avg;
41         if(sum%n!=0){
42             puts("-1");
43             continue;
44         }
45         avg=sum/n;//目标数字
46         printf("%d\n",3*(n-1));
47         for(int i=2;i<=n;i++){
48             op(1,i,(i-a[i]%i)%i);
49             op(i,1,a[i]/i);
50         }
51         for(int i=2;i<=n;i++){
52             op(1,i,sum/n);
53         }
54     }
55     system("pause");
56     return 0;
57 }

 

posted @ 2020-10-26 20:12  Obake  阅读(130)  评论(0编辑  收藏  举报