首页 > 其他分享 >CF1416B Make Them Equal 题解

CF1416B Make Them Equal 题解

时间:2024-02-07 10:13:41浏览次数:27  
标签:cos const struct int 题解 CF1416B Equal include sum

解题思路

观察可以发现,每次操作后序列元素之和不变,那么我们可以将每一次操作看作是 \(a_i\) 向 \(a_j\) 移动了 \(i\times x\)。由此可得,若序列和 \(sum\bmod n\not=0\),那么一定无解,否则一定存在一个合法的操作方案。

因为每次移动时移动的数应为 \(i\) 的倍数,所以 \(a_1\) 可以向任意元素移动任意大小不超过 \(a_1\) 的数,那么我们考虑先将所有数全部移动到 \(a_1\),再由 \(a_1\) 平分给 \(a_2,\dots,a_n\)。但是这种情况先可能存在一个 \(a_j\) 使得 \(a_j\) 不能整除 \(j\),那么我们需要使用 \(a_1\) 先将 \(a_j\) 补为 \(j\) 的倍数然后再全部移向 \(a_1\)。

AC 代码

#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<set>
#define N 100005

int n,a[N],sum,mint[N];
struct ANS{
    int i,j,x;
};

struct Point{
    int cos;
    int val;
    int pos;
};
struct cmp{
    inline bool operator ()(
        const Point A,
        const Point B
    ) const {
        if(A.cos!=B.cos)
            return A.cos<B.cos;
        return A.val>B.val;
    }
};
inline void work(){
    scanf("%d",&n);sum=0;
    std::vector<ANS> ans;
    for(register int i=1;i<=n;++i)
        scanf("%d",&a[i]),sum+=a[i];
    if(sum%n!=0){puts("-1");return;}

    int Average=sum/n;
    
    for(register int i=2;i<=n;++i){
        int res=i-(a[i]%i);if(a[i]%i){
            ans.push_back({1,i,res});
            a[1]-=res,a[i]+=res;
        }ans.push_back({i,1,a[i]/i});
    }

    for(register int i=2;i<=n;++i)
        ans.push_back({1,i,Average});

    printf("%d\n",ans.size());
    for(auto now:ans){
        printf("%d ",now.i);
        printf("%d ",now.j);
        printf("%d\n",now.x);
    }
}
signed main(){
    int T;scanf("%d",&T);
    while(T--) work();
}

标签:cos,const,struct,int,题解,CF1416B,Equal,include,sum
From: https://www.cnblogs.com/UncleSamDied6/p/18010668

相关文章

  • CF1446C Xor Tree 题解
    解题思路与其考虑删除哪些点,不如考虑保留哪些点。考虑到和异或有关,那么我们可以把这些数倒序插入trie树中,然后我们就可以在trie树上跑一个简单的dp:若当前节点为叶子节点,那么保留,返回\(1\);若当前节点在链上,那么直接继承儿子节点;若当前节点有两个儿子,那么更新为较大儿子......
  • CF1922E Increasing Subsequences 题解
    解题思路因为可以有空集,那么我们首先构造第一段最长的连续上升的序列,那么这段序列中共有\(2^{\mids\mid}\)个上升子序列。接下来我们考虑补全剩余的,我们不妨将剩余的部分全部设为连续不增序列,那么设当前位置在第一段中有\(k\)个小于它的,那么添加这个数后可以增加\(2^{k-1}......
  • CF1413C Perform Easily 题解
    解题思路其实是很简单的一道题,考虑计算出所有\(b_i\)在减去每一个\(a_j\)后所有可能的值,将这个值按照从小到大的顺序排序,那么我们可以考虑固定最小值,查找最大值,这个时候从最小值到最大值的区间内应该每一种\(b_i\)都出现了一次。那么,我们可以使用一个桶或者map搭配双指针......
  • 洛谷P10135 暨 USACOJan2024S T2 题解
    题意简述给点一棵有\(n\)个节点的树,在每个时间点都会在某个节点出现一瓶药水,记\(p_i\)为第\(i\)个时间点出现药水的节点,定义一次遍历为从\(1\)号节点走到任意节点,要求在遍历次数最少的情况下拾取最多数量的药水。思维路径首先我们要探讨遍历次数最少的状态是怎样的。由......
  • CF1922B Forming Triangles 题解
    解题思路显然,有以下两种选择的方法:所有边一样长;两条一样长的边,第三条边小于这两条边。然后组合数计算即可。AC代码#include<stdio.h>#include<stdlib.h>#include<algorithm>#include<vector>#definelllonglong#defineN300005intn,a[N];inlinellC3(llx){......
  • CF1922C Closest Cities 题解
    解题思路贪心,能走距离最短的城市就一定走。分别考虑\(x>y\)和\(x<y\)的情况,两种情况分别是从后向前转移和从前往后转移,分别预处理一个前缀和和后缀和即可。AC代码#include<stdio.h>#include<stdlib.h>#include<valarray>#defineN100005#definelllonglongintn......
  • CF1338B Edge Weight Assignment 题解
    解题思路一种不需要树形dp的做法。因为是一颗无根树,所以我们不妨以重心为根。首先考虑边权最少的情况。可以发现这个时候对于任意两个叶子节点,我们可以分别考虑其到根节点的路径,这样对于求其路径的异或值是没有影响的,但是在这种情况下我们可以很方便的讨论其路径的奇偶性。令......
  • ABC335 A~E 题解
    A题目大意输入一个字符串,把这个字符串的最后一位改成4后输出这个字符串。解题思路直接模拟即可AC代码#include<iostream>#include<math.h>#include<time.h>#include<stdio.h>#include<algorithm>#definelllonglonginlinevoidwork(){std::strings;s......
  • P6025 线段树 题解
    解题思路暴力做法从\(l\)到\(r\)枚举每一个数,然后建线段树,记录最大下标,然后计算答案。代码略。时间\(O(n^2)\),期望得分:\(10\)分。优化暴力我们考虑每次枚举不遍历整棵线段树。显然,贪心的,最深的最右边的节点编号最大。那么我们可以发现,如果两颗子树大小相同,那么最大节......
  • csp-j题解
    csp-j题解第一题:小苹果原题洛谷P9748题目描述小Y的桌子上放着\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\)。小苞是小Y的好朋友,每天她都会从中拿走一些苹果。每天在拿的时候,小苞都是从左侧第\(1\)个苹果开始、每隔\(2\)个苹果拿走\(1\)个苹果。随后小苞......