Codeforces 798C Mike and gcd problem【思维+贪心】好题!

探讨通过特定操作使数列的各元素最大公约数大于1的方法及最小步骤。分析不同数对的操作次数,并提出解决策略。

C. Mike and gcd problem
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Mike has a sequence A = [a1, a2, ..., an] of lengthn. He considers the sequence B = [b1, b2, ..., bn] beautiful if thegcd of all its elements is bigger than 1, i.e. .

Mike wants to change his sequence in order to make it beautiful. In one move he can choose an indexi (1 ≤ i < n), delete numbersai, ai + 1 and put numbersai - ai + 1, ai + ai + 1 in their place instead, in this order. He wants perform as few operations as possible. Find the minimal number of operations to make sequenceA beautiful if it's possible, or tell him that it is impossible to do so.

is the biggest non-negative numberd such that d dividesbi for everyi (1 ≤ i ≤ n).

Input

The first line contains a single integer n (2 ≤ n ≤ 100 000) — length of sequenceA.

The second line contains n space-separated integersa1, a2, ..., an (1 ≤ ai ≤ 109) — elements of sequence A.

Output

Output on the first line "YES" (without quotes) if it is possible to make sequenceA beautiful by performing operations described above, and "NO" (without quotes) otherwise.

If the answer was "YES", output the minimal number of moves needed to make sequenceA beautiful.

Examples
Input
2
1 1
Output
YES
1
Input
3
6 2 4
Output
YES
0
Input
2
1 3
Output
YES
1
Note

In the first example you can simply make one move to obtain sequence [0, 2] with .

In the second example the gcd of the sequence is already greater than1


题目大意:

我们有一种操作,选择两个相邻的数(Ai,Ai+1)能够将其变成:(Ai-Ai+1,Ai+Ai+1);

我们希望最终的数组的|Gcd(A1,A2,A3,A4,A5..............)|>1.询问最少需要操作多少步。


思路:


问题的操作是在两个数的基础上进行的。

那么我们不妨只考虑两个数的操作,手写几组数据不难发现,所有写出来的两个数A.B,都会在至多两次操作内完成任务。那么我们可以考虑其性质:

两个数A.B.无非四种情况:
奇数,奇数--------------->操作后变成       偶数,偶数

奇数,偶数--------------->操作后变成       奇数,奇数

偶数,奇数--------------->操作后变成       奇数,奇数

偶数,偶数--------------->操作后变成       偶数,偶数


所以:

如果原来两个数都是偶数的话,那么操作数为0.

如果原来两个数都是奇数的话,那么操作数为1.

如果原来两个数是一奇一偶的话,那么操作数为2.


而后我们考虑结果,其最终可行解为两种情况:

①偶数 偶数的话,那么没有什么异议.

②奇数 奇数的话,只有这两个数相等且>1的话才会满足结果。

其一定不会出现结果是(3 ,6)这种情况的,除非原序列就是这样的。



那么我们不妨将问题推展到三个数,如果结果是(奇数 奇数 奇数)的话,我们肯定原来序列和结果序列是一样的,而且这三个奇数是相等且大于1的。

否则不可能有这样的结果,反之,如果结果是(偶数 偶数 偶数)的话,那么是没有异议的。

所以如果原序列的结果是>1的,那么操作数需要为0.

反之我们将原序列全部变成偶数即可。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int gcd(int x,int y)
{
    return y==0?x:gcd(y,x%y);
}
int a[1500000];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        int gc=0;
        for(int i=0;i<n;i++)gc=gcd(gc,a[i]);
        if(gc>1)
        {
            printf("YES\n0\n");
        }
        else
        {
            printf("YES\n");
            int output=0;
            for(int i=0;i<n-1;i++)
            {
                while(abs(a[i])%2==1)
                {
                    output++;
                    int tmp=a[i];
                    a[i]=a[i]-a[i+1];
                    a[i+1]=tmp+a[i+1];
                }
            }
            while(abs(a[n-1])%2==1)
            {
                output++;
                int tmp=a[n-2];
                a[n-2]=a[n-2]-a[n-1];
                a[n-1]=tmp+a[n-1];
            }
            printf("%d\n",output);
        }
    }
}










### 关于Codeforces中的GCDCodeforces平台上存在多个涉及最大公约数(GCD)概念的问。其中一道具有代表性的目是编号为1025B的“Weakened Common Divisor”,该由著名数学家Ildar引入了一个新的概念——弱化公因数(WCD),即对于一系列整数对列表而言的一种特殊性质[^2]。 具体到这道目的描述如下:给出一个长度为\(n\)的数组\(a\),目标是在所有元素上加上同一个常量\(d\)之后能够找到至少两个不同的位置其值的最大公约数大于等于2,并且要使这个加上的常量尽可能小。此的关键在于通过计算相邻两数之差来间接获取可能存在的公共因子,进而利用这些信息推导出满足条件所需的最小增量\[d\][^4]。 为了高效解决这类基于GCD的问,在算法设计方面通常会采用一些特定技巧: - **差分遍历**:通过对原始序列做适当变换简化问结构; - **快速求解GCD**:借助欧几里得算法迅速定位潜在候选者; - **优化查找过程**:针对所得结果进一步筛选最优方案; 下面是一个Python版本的解决方案片段用于演示如何处理上述提到的任务逻辑: ```python from math import gcd from itertools import pairwise def min_operations_to_weak_gcd(nums): diff_gcd = 0 for prev, curr in pairwise(nums): diff_gcd = gcd(diff_gcd, abs(curr - prev)) if diff_gcd == 1: return -1 factors = get_factors(diff_gcd) result = float('inf') target_modulo = nums[0] % diff_gcd for factor in factors: candidate = ((target_modulo + diff_gcd - (nums[0] % factor)) % factor) result = min(result, candidate) return int(result) def get_factors(n): """Helper function to generate all divisors.""" res = [] i = 1 while i*i <= n: if n % i == 0: res.append(i) if i != n // i: res.append(n//i) i += 1 return sorted(res)[::-1] ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值