D.Make Them Equal

        Codeforces Round #673 (Div. 2)——D. Make Them Equal

2020/9/28
事实证明这题是真的简单,相较于C题复杂的处理我倒觉得这题更简单吧。纯思维题,但是我还是没写出来
题目:
You are given an array a consisting of n positive integers, numbered from 1 to n. You can perform the following operation no more than 3n times:

choose three integers i, j and x (1≤i,j≤n; 0≤x≤109);
assign ai:=ai−x⋅i, aj:=aj+x⋅i.
After each operation, all elements of the array should be non-negative.

Can you find a sequence of no more than 3n operations after which all elements of the array are equal?
题意:
给定一个n个正整数的数组,你每次可以进行一个操作:
选三个数i,j,x,然后ai=ai+i*x,aj=aj+j*x,分析一下就是选一个位置i使得它减少i倍的一个数,并把这个数加到任意一个位置。
要求执行3*n次操作之内能不能使得n个数相同?
分析:
先分析算式,可以知道,如果i位置的数ai是i的倍数,则该位置的数就可以被i个i个全部拿走,那很明显,对于第1个位置的数,它是绝对优的,因为它可以按1的任意倍数(即任意数)分配。
对于不可能的情况:当且仅当n个数的和不是n的倍数的时候无解,该情况无解显而易见,但是为什么只有该情况是无解的呢——这里考虑一个构造过程:
 rep i,2,n
  对于ai,它是否是i的倍数,
   如果是,则直接把ai按照i=i,j=1,x=ai/i,把ai的数全部移到a1.
   如果不是,则直接把a1按照i=1,j=i,x=i-ai%i,把a1的数移到ai,使得ai的数是i的倍数,然后再同理把ai的数全部移到a1.
   ----这里为什么可以确定可以移动呢,因为一开始a1>=1,而2-a2<=1(因为只考虑a2不是2的倍数),然后a1+=a2的值,继续推发现无论数组a的值是多少,都可以满足按照i从2到n的顺序,对于i必有a1>=i-1,且i-ai<=i-1即i-ai<=a1,故每一轮a1都有足够的数分配给ai,使得ai是i的倍数。
到这里,我们可以发现无论什么情况(除去开始讲的-1情况)都能在<=2*(n-1)次操作下把a2到an的值全部转移到a1(即a2到an都变成0)。之后就只需要花n-1次操作把a1的值按平均数一个个分配给a2到an即可(因为a1的位置是可以分配任意数的)
代码:

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define  rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 998244353;
inline ll read() {
    
    
    ll 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 << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
ll fpow(ll a, ll b)
{
    
    
    ll ans = 1;
    while (b)
    {
    
    
        if (b & 1)ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
ll gcd(ll a, ll b) {
    
     return !b ? a : gcd(b, a % b); }
const int N = 1000010;


bool isprime(int n)
{
    
    
    for (int i = 2; i <= sqrt(n); i++)if (n % i == 0)return false;
    return true;
}ll jc[300005];
ll x[10005];
struct s {
    
     ll a, b, c; };
vector<s> v;
priority_queue<pll> p;
int main()
{
    
    
    int t = rd;
    while (t--)
    {
    
    
        v.clear();
        int n = rd;
        ll sum = 0;
        for (int i = 1; i <= n; i++)
        {
    
    
            x[i] = rd;
            sum += x[i];
        }
        if (sum % n == 0)
        {
    
    
            sum /= n;
        }
        else
        {
    
    
            cout << -1 << endl;
            continue;
        }
        int f = 0;
        for (int i = 2; i <= n; i++)
        {
    
    
            if (x[i] % i)
            {
    
    
                struct s a = {
    
     1, i, i - x[i] % i };
                v.push_back(a);
                x[i] += i - x[i] % i;
                a = {
    
     i, 1, x[i] / i };
                v.push_back(a);
            }
            else
            {
    
    
                s a = {
    
     i, 1, x[i] / i };
                v.push_back(a);
            }
        }
        for (int i = 2; i <= n; i++)
        {
    
    
            struct s a = {
    
     1, i, sum};
            v.push_back(a);
        }
        cout << v.size() << endl;
        for (auto p : v)
        {
    
    
            cout << p.a << ' ' << p.b << ' ' << p.c << endl;
        }
    }
    return 0;
}
//cout << (97 * 4 + 95 + 95 * 3 + 88 + 88 * 4 + 87 * 3.5  + 80 * 0.25)/( 4 + 1 + 3 + 1 + 4 + 3.5  + 0.25 );

猜你喜欢

转载自blog.csdn.net/ylwhxht/article/details/108841615