题目大意:给一个长为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<<' ' 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 ",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 ",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 }