D. Make Them Equal 思维构造

传送门

题意

您将得到一个由𝑛个正整数组成的数组array,从1到number编号。您最多可以执行3次以下操作:

选择三个整数𝑖,𝑗和𝑥(1≤𝑖,𝑗≤𝑛;0≤𝑥≤109);
分配𝑎𝑖:= 𝑎𝑖−𝑥⋅𝑖,𝑎𝑗:=𝑎𝑗𝑥⋅𝑖。
每次操作后,数组的所有元素都应为非负数。

您能找到不超过3个运算的序列,之后数组的所有元素都相等吗?

分析

很显然,处理完之后的合法数组每个数字就是数组和的平均数,题目最后还说明不要求操作次数最少,所以我们可以选择一个比较合适的过渡点

如果我们选择i为1的话,那么根据选择的x的不同,𝑥⋅𝑖可以包含所有整数,也就是说此时我们无论选择哪一个j,都可以保证有对应的x,使得操作完之后aj的值为平均值。
而题目要求每次操作完之后数组每一项都为非负数,所以我们可以提前预处理一下,把所有值都转移到a1上,再由a1进行分配

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define x first 
#define y second
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
struct xxx{
    int a,b,c;
};
const int INF = 0x3f3f3f3f;
const int N = 1e4 + 10;
int a[N];
vector<xxx> ans;
int n;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ans.clear();
        scanf("%d",&n);
        int sum = 0;
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
            sum = sum + a[i];
        }
        if(sum % n != 0){
            puts("-1");
            continue;
        }
        int avg = sum / n;
        for(int i = 2;i <= n;i++){
            if(a[i] % i != 0){
                int t = a[i] % i;
                t = i - t;
                a[i] += t;
                ans.push_back({1,i,t});
            }
            ans.push_back({i,1,a[i] / i});
        }
        for(int i = 2;i <= n;i++) ans.push_back({1,i,avg});
        printf("%d\n",(int)ans.size());
        for(auto t:ans) printf("%d %d %d\n",t.a,t.b,t.c);
    }
    return 0;
}

### C++ `multimap` 的使用方法及特性 #### 1. 基本概念 `multimap` 是 C++ STL 提供的一种关联容器,类似于 `map`,但它允许存储多个具有相同键的值。它的定义如下[^4]: ```cpp template <class Key, class T, class Pred = less<Key>, class A = allocator<T> > class multimap { ... }; ``` 其中: - **Key**: 键的数据类型。 - **T**: 映射到的值的数据类型。 - **Pred**: 排序准则,默认为 `less<Key>`,即按键升序排列。 - **A**: 分配器类型。 #### 2. 构造函数 可以通过多种方式创建一个 `multimap` 实例。以下是常见的构造形式[^3]: ```cpp // 创建空的 multimap std::multimap<int, std::string> mmap; // 初始化列表构建 multimap std::multimap<char, int> mmap = { {'a', 1}, {'b', 2}, {'b', 3} }; ``` #### 3. 插入元素 通过成员函数 `.insert()` 可以向 `multimap` 添加新元素。支持单个插入和范围插入[^1]: ```cpp mymultimap.insert({ 'c', 4 }); mymultimap.insert(std::make_pair('d', 5)); ``` #### 4. 访问元素 由于 `multimap` 支持重复键,无法像 `map` 那样直接通过下标访问某个特定键对应的唯一值。可以使用迭代器来遍历所有匹配项: ```cpp for (auto it = mymultimap.lower_bound('b'); it != mymultimap.upper_bound('b'); ++it) { std::cout << it->first << ": " << it->second << "\n"; } ``` #### 5. 删除元素 删除操作可通过指定键名或者迭代器完成。注意,如果存在多条记录对应同一键,则会全部被移除: ```cpp size_t count_removed = mymultimap.erase('b'); std::cout << count_removed << " elements removed.\n"; // 清空整个 multimap mymultimap.clear(); ``` #### 6. 自定义排序 默认情况下,`multimap` 按照键从小到大顺序存储数据。然而,也可以提供自定义比较逻辑实现不同的排序策略[^2]: ```cpp struct CompareSecond { bool operator()(const std::pair<int, std::string>& lhs, const std::pair<int, std::string>& rhs) const { return lhs.second < rhs.second; } }; std::multimap<int, std::string, CompareSecond> customMMap = {{2, "two"}, {1, "one"}}; ``` #### 7. 示例代码 下面给出一段完整的例子展示如何初始化、插入、查询以及清理一个多映射表实例[^1]: ```cpp #include <iostream> #include <map> using namespace std; int main(){ // Initialize with some values multimap<char,int> mmi={{'a',1},{'b',2},{'b',3}}; // Insert new pairs into the multimap mmi.emplace('c',4); mmi.insert({'d',5}); // Iterate over all items and print them out. for(auto& p : mmi){ cout<<p.first<<" -> "<<p.second<<"\n"; } // Find how many entries exist under key 'b' auto range=mmi.equal_range('b'); cout<<"\nEntries found for 'b':\n"; while(range.first!=range.second){ cout<<(*range.first).second<<"\n"; ++range.first; } // Clear contents of the container mmi.clear(); return 0; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值