hdu 6025

来源:互联网 发布:mac粉底液哪个最白 编辑:程序博客网 时间:2024/06/05 03:50

题意:在数列中删除一个数使得所有数的gcd最大;

思路: 

1.用一个前缀数组gd1[]记录前i个数的gcd,一个后缀数组gd2[]记录后i ~ n个数的gcd,当要删除第i个数的时候,数列的gcd为gcd(gd1[i - 1],gd2[i + 1]);

为了使得能删除第一个数和最后一个数,增加了a[0] = a[n + 1] = 0;因为gcd(0,x) == x;

2.当然也可以用线段树进行操作,记录的值为它的线段的gcd,删除基理一样,查询前i- 1的gcd,和i+1之后区间的gcd,然后取gcd;


前缀数组:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<map>#include<string>using namespace std;#define clr(x,y) memset(x,y,sizeof x)const int maxn = 100000 + 10;const double pp = 10e8;typedef long long ll;const ll SMod = 1000000007;int gcd(int x,int y){    return y ? gcd(y,x % y) : x;}int n,m;int a[maxn];int gd1[maxn];int gd2[maxn];int main(){    int Tcase;    scanf("%d",&Tcase);    while(Tcase --)//    while( ~ scanf("%I64d%I64d",&n,&m))    {        scanf("%d",&n);        for(int i = 1; i <= n; i ++)            scanf("%d",&a[i]);        gd1[0] = gd2[n + 1] = 0;        for(int i = 1; i <= n; i ++)        {            gd1[i] = gcd(gd1[i - 1],a[i]);        }        for(int i = n; i >= 1; i --)        {            gd2[i] = gcd(gd2[i + 1],a[i]);        }        int ans = 1;        for(int i = 1; i <= n; i ++)        {            ans = max(ans,gcd(gd1[i - 1],gd2[i + 1]));        }        printf("%d\n",ans);    }    return 0;}

线段树:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 100000 + 10;#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x )typedef long long ll;#define eps 10e-10const ll Mod = 1000000007;struct Tree{    int l;    int r;    int gd;}tree[maxn<<2];int gcd(int x,int y){    return y ? gcd(y,x % y) : x;}int a[maxn];void build(int rt,int l,int r){    tree[rt].l = l;    tree[rt].r = r;    if(l == r)    {        tree[rt].gd = a[l];        return ;    }    int mid = (l + r) >> 1;    build(rt << 1,l,mid);    build(rt<< 1 | 1,mid+1,r);    tree[rt].gd = gcd(tree[rt << 1].gd,tree[rt << 1 | 1].gd);}int query(int rt,int L,int R){    if(tree[rt].l >= L&& tree[rt].r <= R)    {        return tree[rt].gd;    }    int mid = (tree[rt].l + tree[rt].r) >> 1;    int ret = 0;    if(L <= mid)    {        ret = gcd(ret,query(rt<<1,L,R));    }    if(R >= mid + 1)        ret =gcd(ret,query(rt << 1 | 1,L,R));    return ret;}int main(){    int Tcase;    scanf("%d",&Tcase);    while(Tcase --)    {        int n;        scanf("%d",&n);        for(int i = 1; i <= n; i ++)            scanf("%d",&a[i]);        a[0] = a[n + 1] = 0;        build(1,0,n + 1);        int ans = 0;        for(int i = 1; i <= n; i ++)        {            ans = max(ans,gcd(query(1,0,i - 1),query(1,i + 1,n + 1)));        }        printf("%d\n",ans);    }    return 0;}

RMQ:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 100000 + 10;#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x )typedef long long ll;#define eps 10e-10const ll Mod = 1000000007;int a[maxn];int dp[maxn][31];int n;int gcd(int x,int y){    return y ? gcd(y,x % y) : x;}void RMQ_Init(){    for(int i = 0; i <= n + 1; i ++)    {        dp[i][0] = a[i];    }    for(int j = 1; (1 << j) <= n + 1;j ++)    {        for(int i = 0; i + (1 << j) - 1 <= n + 1; i ++)        {            dp[i][j] = gcd(dp[i][j - 1],dp[i + (1 << (j - 1))][j - 1]);        }    }}int query(int l,int r){    int k = 0;    while((1 << (k + 1)) <= (r - l + 1))        k ++;    return gcd(dp[l][k],dp[r - (1 << k) + 1][k]);}int main(){    int Tcase;    scanf("%d",&Tcase);    while(Tcase --)    {        scanf("%d",&n);        for(int i = 1; i <= n; i ++)            scanf("%d",&a[i]);        RMQ_Init();//        int ans = max(query(2, n), query(1, n - 1));        int ans = 0;        for(int i = 1; i <= n; i ++)        {//            cout << gcd(query(0, i - 1),query(i + 1, n + 1)) << endl;            ans = max(ans, gcd(query(0, i - 1),query(i + 1, n + 1)));        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击