天天看点

CodeForces - 894C Marco and GCD Sequence 构造+思维

http://codeforces.com/problemset/problem/894/C

题意:有数列a[1],a[2],...,a[n],按照方法gcd(a[i],a[i+1],...a[j]) (i<=j),求出所有gcd放入set。现在反过来已知set,求其中一组可能的数列。

题解:比赛时的想法是,①求出所有数的gcd为GCD,一定要等于最小那个数 ,②这个set就是其中的一组解(满足单点gcd)。后来被hack了,数据是1 3 8 12。8和12产生了新的区间gcd。所以应该加入限制,set中每个数需要存在,保证单点gcd。然后每个数前加一个GCD,这样就保证了区间gcd,限制了新的区间gcd的产生。

代码:

#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 100000 + 5;
const int M = N * N + 5;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
int a[N];

int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

int main(){
	int n,GCD;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(i==1){
			GCD=a[i];
			continue;
		}
		GCD=gcd(GCD,a[i]);
	}
	if(GCD!=a[1]){
		puts("-1");
		return 0;
	}
	printf("%d\n",2*n);
	for(int i=1;i<=n;i++){
		cout<<GCD<<" "<<a[i]<<" ";
	}
	return 0;
}