【codeforces 798C】Mike and gcd problem

【题目链接】:http://codeforces.com/contest/798/problem/C

【题意】

给你n个数字;
要求你进行若干次操作;
每次操作对第i和第i+1个位置的数字进行;

a[i]变为a[i]-a[i+1],a[i+1]变为a[i]+a[i+1];
然后问你能不能通过以上变换使得最后所有元素的gcd>1

【题解】

答案总是存在的;
因为把这个操作进行两次可以得到-2*a[i+1],2*a[i]
也就是如果对每相邻的元素进行操作,最后都能使得这两个元素都变成偶数;
最后gcd最少都为2了;
则:
如果一开始所有元素的gcd>1则直接输出0;
等于1;
假设改变一次后的gcd为d
则d|a[1..i-1]且d|a[i+2..n]
且d|a[i]-a[i+1]且d|a[i]+a[i+1]
因为由d|x和d|y可以得到
d|x+y以及d|x-y
所以
d|2*a[i]且d|2*a[i+1]
这样就大概猜测要使得每个元素都变成偶数吧.
每个元素都贪心地让他变成偶数就好了;
(有了“这个操作进行两次可以得到-2*a[i+1],2*a[i]”这个结论,我们可以放心地进行贪心,当然不一定是都要进行两次操作,比如a[i]和a[i+1]都是奇数,则只要进行一次操作,因为一次操作后两个数的奇偶性都会因为加、减了一个奇数而发生改变);
只要第i个元素没有变成偶数就一直进行这个操作;
然后第n个元素如果最后在前n-1个元素进行操作之后没有变成偶数;
则必然可以对n-1,n操作两次使得a[n-1]保留仍旧是偶数,a[n]也变成了偶数;
因为
a[n-1]是偶数了,a[n]是奇数
第一次操作后
a[n-1]变成奇数,a[n]还是奇数;
再进行一次操作后
a[n-1]变成偶数,a[n]也变成偶数;
具体看代码

【Number Of WA

1

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e5+100;
const int INF = 21e8;

int n;
LL a[N],now;

LL gcd(LL a,LL b)
{
    if (b==0)
        return a;
    else
        return gcd(b,a%b);
}

LL tgcd(LL a,LL b)
{
    return gcd(abs(a),abs(b));
}

void change(int x,int y)
{
    LL ta = a[x]-a[y],tb = a[x]+a[y];
    a[x] = ta,a[y] = tb;
}

int main()
{
    //cout << tgcd(12,3)<<endl;
    //freopen("F:\\rush.txt","r",stdin);
    ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf就别用了!
    cin >> n;
    rep1(i,1,n)
        cin >> a[i];
    now = tgcd(a[1],a[2]);
    rep1(i,3,n)
        now = tgcd(now,a[i]);
    cout <<"YES"<<endl;
    if (now>1)
    {
        cout <<0<<endl;
        return 0;
    }
    int ans = 0;
    for (int i = 1;i <= n-1;i++)
    {
        while ((a[i]%2)!=0)
        {
            change(i,i+1);
            ans++;
        }
    }
    while ((a[n]%2)!=0)
    {
        change(n-1,n);
        ans++;
    }
    cout << ans << endl;
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(87)  评论(0编辑  收藏  举报