Educational Codeforces Round 100 (Rated for Div. 2) B. Find The Array

详细题解

题目:Educational Codeforces Round 100 (Rated for Div. 2) B. Find The Array

在这里插入图片描述

题意 :

给我们一个有n个元素的数组a
然后要我们找一个数组b
需要满足三个条件

  • 对于b数组中的每一对元素 ( b i , b i + 1 ) (b_i,b_{i + 1}) (bi,bi+1),要么 b i b_i bi可以整除 b i + 1 b_{i+1} bi+1,要么 b i + 1 b_{i+1} bi+1可以整除 b i b_{i} bi(或者互相整除也行)
  • 2 ∑ 1 n ( ∣ a i − b i ∣ ) < S 2\sum_1^n(\mid a_i - b_i\mid)<S 21n(aibi)<S (其中 S = ∑ 1 n a i S=\sum_1^na_i S=1nai
  • 对于所有 b i b_i bi,有 1 ≤ b i ≤ 1 0 9 1\leq b_i \leq10^9 1bi109

例:

a a a数组是 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
我们可以变成
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
此时 S = 15 S=15 S=15,即b数组和为 S ′ S^{'} S S ′ = = 4 + 2 + 0 + 2 + 4 = 12 S^{'}= =4+2+0+2+4=12 S==4+2+0+2+4=12符合条件

输入:

4
5
1 2 3 4 5
2
4 6
2
1 1000000000
6
3 4 8 1 2 3

输出:

3 3 3 3 3
3 6
1 1000000000
4 4 8 1 3 3

思路:

非常容易的发现1是万能的除0以外任何数都可以被1整除,所以可以用1填补到一些位置
其中还有一个条件就是每一位的方差的两倍之和要小于a数组的总和S
非常巧妙地想到了可以对a数组直接进行操作,但是a数组中相邻的位置不一定是能够整除的
所以对a数组进行替换1来试着解决这个问题
虽然这样就会产生很大的方差,但是发现我们只产生一个位置的方差,然后另一个位置的方差是0
所以我们的这两个位置方差和其实就是一个被改成1的方差的两倍
极端情况如果每两个位置都这样的话
那我们为了让每一个位置不超过原本的数,我们只能改这两个位置中数字小的那个数字,这样总和只会减小
但是发现如果改了一个位置,那么这位置的左右两侧一定不能改,因为每两个位置只能改一个
所以我们考虑间隔一个改一个,为了满足方差和
我们直接算出从第一个开始改和从第二个开始改,步长都是2,这两组数的和
实际就是奇数位和偶数位
改其中总和小的那个
也就是得到了:偶大改奇,奇大改偶

思考:

在写题的时候脑子抽筋,为什么不用考虑原数组的奇偶性呢?
也就是会不会奇数的时候如果改了奇数最后一位数没有另一个方差为0的数和他平摊,会不会大于数组之和呢?
设{ a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3}为数组a
那么假设: a 1 + a 3 < a 2 a_1 + a_3 < a_2 a1+a3<a2 偶大改奇
b b b数组{ 1 , a 2 , 1 1,a_2,1 1,a2,1},此时最后一个数被改了,没有人平摊了
a , b a,b a,b数组可得
S = a 1 + a 2 + a 3 S=a_1+a_2+a_3 S=a1+a2+a3
S ′ = 2 ∗ ( a 1 + a 3 ) − 2 S^{'}=2*(a_1+a_3)-2 S=2(a1+a3)2
b b b数组合法及要求: S ′ ≤ S S^{'}\leq S SS
∵ a 2 > a 1 + a 3 \because a_2>a_1+a_3 a2>a1+a3
∴ S > 2 ( a 1 + a 3 ) \therefore S>2(a_1+a_3) S>2(a1+a3)
可得 S > 2 ( a 1 + a 3 ) − 2 S>2(a_1+a_3)-2 S>2(a1+a3)2
S ′ > S S^{'}> S S>S
所以还是满足的呀

代码

#include <iostream>
#include <algorithm>

#define int long long
using namespace std;

const int N = 55;
int a[N];
void solve()
{   
    int n; cin >> n;
    int suml = 0, sumr = 0;
    // 如果总共有奇数个
    for(int i = 1 ; i <= n ; i ++)
    {
        cin >> a[i];
        if(i % 2) suml += a[i];
            // 如果是2的倍数
        else sumr += a[i];
    }

    if(suml > sumr)// 如果奇数大于偶数, 那么改偶数
        for(int i = 1 ; i <= n ; i ++)
        {
            if(i % 2 == 0) cout << 1 << " ";
            else cout << a[i] << " ";
        }
    else 
        for(int i = 1 ; i <= n ; i ++)
        {
            if(i % 2 == 0) cout << a[i] << " ";
            else cout << 1 << " ";
        }
    cout << endl;
    return ;
}


signed main()
{
    int _; cin >> _;
    while(_--) solve();
    return 0;
}
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值