Coprime Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 217 Accepted Submission(s): 126
Problem Description
Do you know what is called ``Coprime Sequence''? That is a sequence consists of n positive integers, and the GCD (Greatest Common Divisor) of them is equal to 1.
``Coprime Sequence'' is easy to find because of its restriction. But we can try to maximize the GCD of these integers by removing exactly one integer. Now given a sequence, please maximize the GCD of its elements.
Input
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, there is an integer n(3≤n≤100000) in the first line, denoting the number of integers in the sequence.
Then the following line consists of n integers a1,a2,...,an(1≤ai≤109), denoting the elements in the sequence.
Output
For each test case, print a single line containing a single integer, denoting the maximum GCD.
Sample Input
Sample Output
1
2
2
//T 组数据,n 个数,开始时,n 个数 gcd 为 1 ,现可以任意抽走一个数,问剩下数最大 gcd 是多少?
// st 表很好做,O(n*logn) + n * O(n) 的时间
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 #define MX 100005 6 7 int n,m; 8 int dp[MX][20]; 9 int mi[MX]; 10 int data[MX]; 11 12 int gcd(int a,int b) 13 {return b==0?a:gcd(b,a%b);} 14 15 void build() 16 { 17 mi[0]=-1; 18 for (int i=1;i<=n;i++) 19 { 20 mi[i]=((i&(i-1))==0) ? mi[i-1]+1:mi[i-1]; //注意位运算优先级很低 21 dp[i][0]=data[i]; 22 } 23 for (int k=1;k<=mi[n];k++) 24 { 25 for (int i=1; (i+(1<<k)-1)<=n ;i++) 26 { 27 dp[i][k]=gcd(dp[i][k-1],dp[i+(1<<(k-1))][k-1]); 28 } 29 } 30 } 31 32 int find_(int a,int b) 33 { 34 int x = mi[b-a+1]; 35 return gcd(dp[a][x],dp[b-(1<<x)+1][x]); 36 } 37 38 int main() 39 { 40 int T; 41 cin>>T; 42 while (T--) 43 { 44 scanf("%d",&n); 45 for (int i=1;i<=n;i++) 46 scanf("%d",&data[i]); 47 build(); 48 int ans = 1; 49 for (int i=1;i<=n;i++) 50 { 51 int res; 52 if (i==1) 53 res = find_(2,n); 54 else if (i==n) 55 res = find_(1,n-1); 56 else 57 res = gcd(find_(1,i-1),find_(i+1,n)); 58 ans = max(ans,res); 59 } 60 printf("%d\n",ans); 61 } 62 }
强行上log n 啊,啊哈哈,其实,只要从左向右扫一遍,存储gcd前缀和,再从右向左扫一遍,存gcd后缀和,然后枚举要剔除的数即可