首页 技术 正文
技术 2022年11月21日
0 收藏 512 点赞 3,385 浏览 4400 个字

题意:在给定的数组里,寻找一个最长的序列,满足ai-2+ai-1=ai。并输出这个序列。

很容易想到一个DP方程

dp[i][j]=max(dp[k][i])+1. (a[k]+a[i]==a[j],1<=k&&k<i)

dp[i][j]表示序列最后两位是a[i],a[j]时的最长长度。

这个方程状态是O(n^2),转移是O(n),总复杂度是O(n^3)会超时。

进一步思考会发现转移这里是可以优化的。实际上我们只需要知道离i最近的那个满足a[k]+a[i]==a[j]的k就行,即最大k。

举个例子

2 3 -1 2 1 3

当i=5,j=6,即ai=1,aj=3时,这时需要找一个ak=2的,显然a1和a4满足,我们会选择a4而不是a1。因为可以转移到a1的状态一定都可以转移到a1,但能转移到a4的状态却不一定都能转移到a1,因此dp[4][5]>=dp[1][5]。这样我们只需要在遍历数组的时候维护数组每个数的最大的下标即可。这里使用hash来做。

我用了stl的hash_map。最后需要逆序输出结果。另外注意卡内存,要用short。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<hash_map>#include<ext/hash_map>using namespace std;using __gnu_cxx::hash_map;hash_map <int,short> has;];][];void output(int n,int x,int y){    if(!n) return ;    output(n-,y-x,x);    ) printf("%d",y-x);    else printf(" %d",y-x);}int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,,sizeof(dp));        ; i<=n; ++i)        {            scanf("%d",&a[i]);            ; j<i; ++j)                dp[j][i]=;        }        )        {            printf(]);            continue;        }        has.clear();        ,x=a[],y=a[];        ; i<=n; ++i)        {            ; j<=n; ++j)            {                hash_map<int,short>::iterator it=has.find(a[j]-a[i]);                if(it!=has.end())                    dp[i][j]=dp[it->second][i]+;                if(dp[i][j]>ans)                {                    ans=dp[i][j];                    x=a[i];                    y=a[j];                }            }            has[a[i]]=i;        }        printf("%d\n",ans);        ans-=;        output(ans,x,y);        if(ans) printf(" ");        printf("%d %d\n",x,y);    }    ;}

当然也可以定义状态 dp[i][j]为序列开头两个数字是ai,aj的最长长度。这样就可以正序输出了。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<hash_map>#include<ext/hash_map>using namespace std;using __gnu_cxx::hash_map;hash_map <int,short> has;];][];int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,,sizeof(dp));        ; i<=n; ++i)        {            scanf("%d",&a[i]);            ; j<=n; ++j)                dp[i][j]=;        }        has.clear();        ,x=a[],y;        ; --i)        {            ; j>=; --j)            {                hash_map<int,short>::iterator it=has.find(a[i]+a[j]);                if(it!=has.end())                {                    dp[j][i]=dp[i][it->second]+;                }                if(ans<dp[j][i])                {                    ans=dp[j][i];                    x=a[j];                    y=a[i];                }            }            has[a[i]]=i;        }        ans++;        printf("%d\n",ans);        printf("%d",x);        ; i<=ans; ++i)        {            printf(" %d",y);            int t=y;            y=x+y;            x=t;        }        printf("\n");    }    ;}

下面是自己实现的hash。

这个用绝对值取模的hash函数。跑了4s+。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>using namespace std;];][];pair<];static const int mask=0x7fff;void init(){    ; i<=mask; ++i) has[i].first=-;}int find(int x){    int key=abs(x)%mask;    while(has[key].first!=x)    {        )            ;        key=(key+)%mask;    }    return has[key].second;}void insert(int x,int val){    int key=abs(x)%mask;    )    {        if(has[key].first==x)        {            has[key].second=val;            return ;        }        key=(key+)%mask;    }    has[key].first=x;    has[key].second=val;}int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,,sizeof(dp));        init();        ; i<=n; ++i)        {            scanf("%d",&a[i]);            ; j<=n; ++j)                dp[i][j]=;        }        ,x=a[],y;        ; --i)        {            ; j>=; --j)            {                int it=find(a[i]+a[j]);                )                {                    dp[j][i]=dp[i][it]+;                }                if(ans<dp[j][i])                {                    ans=dp[j][i];                    x=a[j];                    y=a[i];                }            }            insert(a[i],i);        }        ans++;        printf("%d\n",ans);        printf("%d",x);        ; i<=ans; ++i)        {            printf(" %d",y);            int t=y;            y=x+y;            x=t;        }        printf("\n");    }    ;}

这个是用&的hash函数。跑了1s+。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<hash_map>#include<ext/hash_map>using namespace std;];][];pair<];static const int mask=0x7fff;int Hash(int val){    return val&mask;}void init(){    ; i<=mask; ++i) has[i].first=-;}int find(int x){    int key=x&mask;    while(has[key].first!=x)    {        )            ;        key=(key+)&mask;    }    return has[key].second;}void insert(int x,int val){    int key=x&mask;    )    {        if(has[key].first==x)        {            has[key].second=val;            return ;        }        key=(key+)&mask;    }    has[key].first=x;    has[key].second=val;}int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,,sizeof(dp));        init();        ; i<=n; ++i)        {            scanf("%d",&a[i]);            ; j<=n; ++j)                dp[i][j]=;        }        ,x=a[],y;        ; --i)        {            ; j>=; --j)            {                int it=find(a[i]+a[j]);                )                {                    dp[j][i]=dp[i][it]+;                }                if(ans<dp[j][i])                {                    ans=dp[j][i];                    x=a[j];                    y=a[i];                }            }            insert(a[i],i);        }        ans++;        printf("%d\n",ans);        printf("%d",x);        ; i<=ans; ++i)        {            printf(" %d",y);            int t=y;            y=x+y;            x=t;        }        printf("\n");    }    ;}

最后这个是watash写的hash_map。跑了1s+。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<hash_map>#include<ext/hash_map>using namespace std;];][];struct Hash{    static const int mask = 0x7fff;    ], q[];    void clear()    {        ; i <= mask; ++i)            q[i] = -;    }    int& operator[](int k)    {        int i = k & mask;         && p[i] != k; i = (i + ) & mask);        p[i] = k;        return q[i];    }} hash;int main(){    int n;    bool blank=false;    while(scanf("%d",&n)!=EOF)    {        if(blank) printf("\n");        else  blank=true;        memset(dp,,sizeof(dp));        hash.clear();        ; i<=n; ++i)        {            scanf("%d",&a[i]);            ; j<=n; ++j)                dp[i][j]=;        }        ,x=a[],y;        ; --i)        {            ; j>=; --j)            {                int it=hash[a[i]+a[j]];                )                {                    dp[j][i]=dp[i][it]+;                }                if(ans<dp[j][i])                {                    ans=dp[j][i];                    x=a[j];                    y=a[i];                }            }            hash[a[i]]=i;        }        ans++;        printf("%d\n",ans);        printf("%d",x);        ; i<=ans; ++i)        {            printf(" %d",y);            int t=y;            y=x+y;            x=t;        }        printf("\n");    }    ;}
下一篇: mysql批量写入
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,991
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,506
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,349
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,134
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,766
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,844