从n个数中选n-1个数字使得他们的gcd最大

思路:求一个前缀和一个后缀

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N],t[N],s[N];
int T,n,ans;

int gcd(int x,int y)
{
    if(y == 0) return x;
    return gcd(y,x % y);
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        ans = 0;
        for(int i = 1;i <= n; ++i)
        {
            scanf("%d",&a[i]);
            if(i == 1) s[i] = a[i];
            else s[i] = gcd(s[i - 1],a[i]);
        }
        t[n] = a[n];
        for(int i = n - 1;i >= 1; --i)
            t[i] = gcd(t[i + 1],a[i]);
        for(int i = 1;i <= n; ++i)
        {
            if(i == 1) ans = max(ans,t[2]);
            else if(i == n) ans = max(ans,s[n - 1]);
            else ans = max(ans,gcd(s[i - 1],t[i + 1]));
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

类似的:从n个数中选n-1个数字使得他们的异或值最大

https://ac.nowcoder.com/acm/contest/549/D

#include<bits/stdc++.h>
using namespace std;

const int N = 5e6 + 10;
int a[N],t[N],s[N];
int T,n,ans;

int main()
{
    while(~scanf("%d",&n))
    {
        ans = 0;
        for(int i = 1;i <= n; ++i)
        {
            scanf("%d",&a[i]);
            if(i == 1) s[i] = a[i];
            else s[i] = s[i - 1] | a[i];
        }
        t[n] = a[n];
        for(int i = n - 1;i >= 1; --i)
            t[i] = t[i + 1] | a[i];
        for(int i = 1;i <= n; ++i)
        {
            if(i == 1) ans = max(ans,t[2]);
            else if(i == n) ans = max(ans,s[n - 1]);
            else ans = max(ans,s[i - 1] | t[i + 1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}