codeforces 798c

比賽的時候讀錯題+在電腦前時間很少(搞完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 100005

using 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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章