codeforces 798c

来源:互联网 发布:协同过滤算法java代码 编辑:程序博客网 时间:2024/06/07 06:17

比赛的时候读错题+在电脑前时间很少(搞完ab之后就在实验室会宿舍的路上了orz)。。再加上自己构造能力很差。。妥妥的放过了一道c题orz。看来构造(数学yy)能力还得加强

题目:
http://codeforces.com/problemset/problem/798/C
题目大意:
给你一个有序的数,需要你将这个序列构造成一个gcd(a1,a2,a3..an) > 2的序列
有如下操作
[ai,ai+1] -> [ai+1 - ai,ai+1 + ai]
该操作每次需要花费1个单位的操作次数

我们可以令gcd(x,y) 则有 -> gcd(x - y,x + y) = d
设有gcd(p,q) = 1,则有gcd(pd,qd) = d
有pd = x - y,qd = x + y
则2x = (p + q)d,2y = (q - p)d
该操作可以使公因子*1或者*2
所以,我们可以考虑一下奇偶的问题:
两个都是偶数,不需要操作
两个都是奇数,操作一次变成偶数
一个奇数一个偶数,操作一次变成两个都是奇数,再操作一次变成两个都是偶数

先预处理如果所有的gcd已经满足要求,如果不满足再进行操作
我们只需要贪心就好了,第一次将所有两两挨着的奇数都变成偶数
第二次肯定没有挨着的奇数了,就把一奇一偶操作两次变成偶数,答案就出来了orz。(果然我比较菜)

附上代码:

/*@resources: codeforces798c@date: 2017-4-25@author: QuanQqqqq@algorithm: 构造 greedy*/#include <bits/stdc++.h>#define MAXN 100005using namespace std;int gcd(int a,int b){    int c = a % b;    while(c){        a = b;        b = c;        c = a % b;    }    return b;}int main(){    int n,tmp,num[MAXN];    scanf("%d",&n);    for(int i = 0;i < n;i++){        scanf("%d",&num[i]);    }    int res = gcd(num[0],num[1]);    for(int i = 2;i < n;i++){        res = gcd(res,num[i]);    }    printf("YES\n");    if(res > 2 || n == 1){        printf("0\n");        return 0;    }    int ans = 0;    for(int i = 0;i < n;i++){        if(num[i] & 1){            if(num[i + 1] & 1 && i + 1 < n){                ans++;                tmp = num[i];                num[i] -= num[i + 1];                num[i + 1] += tmp;                i++;            }        }    }    for(int i = 0;i < n;i++){        if(num[i] & 1 || (i + 1 < n && (num[i + 1] & 1))){            ans += 2;            tmp = num[i];             num[i] -= num[i + 1];            num[i + 1] += tmp;            tmp = num[i];            num[i] -= num[i + 1];            num[i + 1] += tmp;            i++;        }    }    printf("%d\n",ans);}
0 0
原创粉丝点击