2017中国大学生程序设计竞赛 - 女生专场C【前后缀GCD】
【题意】:去除数列中的一个数字,使去除后的数列中所有数字的gcd尽可能大。
【分析】:
数组prefixgcd[],对于prefixgcd[i]=g,g为a[0]-a[i]的GCD,称为前缀GCD。
数组suffixgcd[],对于suffixgcd[i]=g,g为a[i]-a[n-1]的GCD,称为后缀GCD。
有了这两个GCD值的数组,那么去掉a[i]的GCD为gcd(prefixgcd[i - 1], suffixgcd[i + 1]),从中找出最大值即可。
【代码】:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define ll long long #define inf 0x3fffffff using namespace std; const int maxn=100000 + 10;; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int main() { int t; int n,ans; int a[maxn],l[maxn],r[maxn]; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); l[0]=a[0]; r[n-1]=a[n-1];//标记前缀起点&&后缀起点 for(int i=1;i<n;i++) { l[i]=gcd(a[i],l[i-1]);//递归求前缀GCD,挖去i,则从前枚举 } for(int i=n-2;i>=0;i--) { r[i]=gcd(a[i],r[i+1]);//递归求后缀GCD,挖去i,则从后枚举 } ans = max(r[1],l[n - 2]);//处理边界情况 for(int i=1;i<n-1;i++) ans=max(ans,gcd(l[i-1],r[i+1])); //分而治之的思想 printf("%d\n",ans); } return 0; }
前缀思想
http://www.jianshu.com/p/1df6305187b0
http://www.tuicool.com/articles/2IneMv
http://www.tuicool.com/articles/2IneMv
https://www.so.com/s?q=Codeforces+Round+%23236+(Div.+2)__Upgrading+Array-&src=se_zoned