您的位置:首页 > 其它

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

2017-04-22 20:36 405 查看
题目链接
题意:
每次可以改变第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 0x3f3f3f3f
using 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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: