Codeforces Round #410 (Div. 2) Mike and gcd problem 思维

来源:互联网 发布:加内特2004季后赛数据 编辑:程序博客网 时间:2024/05/29 03:41

题目链接
题意:
每次可以改变第i和i+1两个数 使他们分别变成 ai-ai+1 ai+ai+1  问你有没有可能使给出的n个数的gcd大于1 
能则输出yes和最小步数 否则输出no

思路:
        对于这个题首先要明白一点题目中不可能出现no的情况,因为对于两个数ai 和ai+1 如果改变两次的话你会发现
两个数变成了 -2*ai+1 2*ai  所以也就是说只要改变两次就会使两个数最起码有一个最大公约数为2
        那么对于这个题我们可以对一开始所有的数取一个gcd如果满足题意则直接输出yes
否则的话那么必须把所有的数变成偶数  也就是说最后他们的最大公约数必须为偶数
我们可以用反证法来证明一下,
如果当前两个数 x y 互质的话 我们假设 改变之后他们的gcd为一个奇数k>1  那么有
      (x-y)%k==0&&(x+y)%k==0 
 那么由第一式子 同余定理可得  x y 同余 即 x%k==y%k=a(我们假设的  a>0&&a<k) 
那么 (x+y)%k==(2*a)%k==0   因为k是奇数 则 a必等于0 那么k就为 x和y之间的一个gcd 则与x y互质矛盾 ,由此可得 k为偶数
        那么对于两个数 如果全为奇数则只需变换一步  如果前面的为奇数后面的为偶数则变换两次 前面为偶数后面为奇数则不变换

    

#include<bits/stdc++.h>#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 100000007#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int maxn=1e5+10;int n,a[maxn];ll gcd(ll b,ll c){if(b==0)return c;return c==0?b:gcd(c,b%c);}int main(){Ri(n);ll tmp=0;for(int i=1;i<=n;i++){ Ri(a[i]); tmp=gcd(tmp,a[i]);  }  if(tmp>1){cout<<"YES"<<endl;cout<<0<<endl;} else{ll ans=0;a[n+1]=0;for(int i=1;i<=n;i++){if(a[i]&1){if(a[i+1]&1){ll x=a[i]-a[i+1];ll y=a[i]+a[i+1];a[i]=x;a[i+1]=y;ans+=1;}else{ll x=-2*a[i+1];ll y=a[i]*2;a[i]=x;a[i+1]=y;ans+=2;}}}cout<<"YES"<<endl;cout<<ans<<endl;}return 0;}     


0 0