题解 CF798C 【Mike and gcd problem】
偶然间看到这么好的题目
发现居然没有一篇题解。。。
所以我来安利一篇别人的题解
原帖 https://blog.csdn.net/mengxiang000000/article/details/71155450
题目大意:
我们有一种操作,选择两个相邻的数(Ai,Ai+1)能够将其变成:(Ai-Ai+1,Ai+Ai+1);
我们希望最终的数组的|Gcd(A1,A2,A3,A4,A5..............)|>1.询问最少需要操作多少步。
思路:
问题的操作是在两个数的基础上进行的。
那么我们不妨只考虑两个数的操作,手写几组数据不难发现,所有写出来的两个数A.B,都会在至多两次操作内完成任务。那么我们可以考虑其性质:
两个数A.B.无非四种情况: 奇数,奇数--------------->操作后变成 偶数,偶数
奇数,偶数--------------->操作后变成 奇数,奇数
偶数,奇数--------------->操作后变成 奇数,奇数
偶数,偶数--------------->操作后变成 偶数,偶数
所以:
如果原来两个数都是偶数的话,那么操作数为0.
如果原来两个数都是奇数的话,那么操作数为1.
如果原来两个数是一奇一偶的话,那么操作数为2.
而后我们考虑结果,其最终可行解为两种情况:
①偶数 偶数的话,那么没有什么异议.
②奇数 奇数的话,只有这两个数相等且>1的话才会满足结果。
其一定不会出现结果是(3 ,6)这种情况的,除非原序列就是这样的。
那么我们不妨将问题推展到三个数,如果结果是(奇数 奇数 奇数)的话,我们肯定原来序列和结果序列是一样的,而且这三个奇数是相等且大于1的。
否则不可能有这样的结果,反之,如果结果是(偶数 偶数 偶数)的话,那么是没有异议的。
所以如果原序列的结果是>1的,那么操作数需要为0.
反之我们将原序列全部变成偶数即可。
Ac代码:
#include<bits/stdc++.h>
using namespace std;
int a[1555555],n,i,j,gc,ans,t;
int gcd(int x,int y)
{
if(y==0)
{
return x;
}
else
{
return gcd(y,x%y);
}
}
int main()
{
cin>>n;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
gc=gcd(gc,a[i]);
}
if(gc>1)
{
cout<<0;
}
else
{
for(i=0;i<n-1;i++)
{
while(abs(a[i])%2==1)
{
ans++;
t=a[i];
a[i]=a[i]-a[i+1];
a[i+1]=t+a[i+1];
}
}
while(abs(a[n-1])%2==1)
{
ans++;
t=a[n-2];
a[n-2]=a[n-2]-a[n-1];
a[n-1]=t+a[n-1];
}
if(ans)
{
cout<<ans;
}
else
{
cout<<-1;
}
}
return 0;
}