#include using namespace std; const int N = 110; int a[N]; int Left[N], Right[N]; //最大公约数,辗转相除法 int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } /** * 测试数据: 5 12 36 24 18 48 结果:6 6 6 12 6 */ int main() { int n; cin >> n; //读入数据 for (int i = 1; i <= n; i++) cin >> a[i]; //类似于递推式获取前1~(i-1)的最大公约数记录到Left[i]中。 for (int i = 1; i <= n; i++) Left[i] = gcd(Left[i - 1], a[i]); //类似于递推式获取后n~(i+1)的最大公约数记录到Right[i]中。 for (int i = n; i >= 1; i--) Right[i] = gcd(a[i], Right[i + 1]); //根据性质3,可以通过左边最大公约和右边最大公约计算出去掉当前数字的最大公约 for (int i = 1; i <= n; i++) cout << gcd(Left[i - 1], Right[i + 1]) << " "; //时间分析:O(3*n) //如果去掉每一个,分别进行重新计算的话,外层循环贡献n,内层还需要一层遍历所有剩余数字,可以认为是O(N^2)级。 //这样通过性质3,就可以实现平方级别时间复杂度到线性复杂度的进化。 //究其原因,就是空间换时间,把已知的结果保存下来,避开了重复的计算。 return 0; }