版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24477135/article/details/52831925
题目大意:
给你n个数,每次取任意三个a , b , c,任取其中两个的gcd = d , 将d , d放回原数列。问经过n-2次后哪些数可能剩下。
思路:求两两的gcd,对gcd和原数列求gcd,知道不在产生新的gcd即可。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 1005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define ULL unsigned long long
#define FOR(i , n) for(int i = 1 ; i<= n ; i ++)
typedef pair<int , int> pii;
#define INF 100000000
int n;
int g[maxn] , a[maxn];
int gcd(int a , int b)
{
if(b == 0) return a;
else return gcd(b , a % b);
}
int main()
{
int t ;
scanf("%d" , &t);
while(t--)
{
mem(g , 0);
scanf("%d" , &n);
for(int i = 0 ; i < n ; i ++)
{
scanf("%d" , &a[i]);
}
for(int i = 0 ; i < n ; i ++)
{
for(int j = i + 1 ; j < n ; j ++)
{
g[gcd(a[i] , a[j])] = 1;
}
}
int flag = 1 , len = 1;
while(len < n - 2 && flag)
{
flag = 0;
len ++;
for(int i = 1 ; i <= 1000 ; i ++ )
{
if(g[i])
{
for(int j = 0 ; j < n ; j ++)
{
int tmp = gcd(i , a[j]);
if(!g[tmp])
{
flag = 1;
g[tmp] = 1;
}
}
}
}
}
flag = 0;
for(int i = 1 ; i <= 1000 ; i ++)
{
if(g[i])
{
if(!flag)
{
flag = 1;
printf("%d" , i);
}
else printf(" %d" , i);
}
}
cout << endl;
}
return 0;
}