【JZOJ4915】最长不下降子序列

来源:互联网 发布:php登录页面完整代码 编辑:程序博客网 时间:2024/06/07 17:59

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

我们看D150,一定有循环节。

然后找到循环节,显然每个循环节至多取一个数。

然后剩余部分加上中间的一部分循环节做一次lis,加上剩余循环节的个数即为答案。

Code

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 151#define M 100001#define ll long longusing namespace std;int a[M];int pos[N];int d[M];int main(){    freopen("lis.in","r",stdin);    freopen("lis.out","w",stdout);    ll n;    scanf("%lld",&n);    int t0,A,B,C,D;    scanf("%d %d %d %d %d",&t0,&A,&B,&C,&D);    int t=t0,now=n;    a[++a[0]]=t;    fo(i,2,n)    {        t=(A*t*t+B*t+C)%D;        if(pos[t]) {now=i;break;}        pos[t]=i;        a[++a[0]]=t;    }    int p=now-pos[t],qq=0,w=a[0];    fo(i,1,p)    {        if(a[0]+p>n) break;        fo(j,a[0]+1,a[0]+p) a[j]=a[j-p];        a[0]+=p;        qq+=p;    }    while(qq<=w)    {        if(a[0]+p>n) break;        fo(j,a[0]+1,a[0]+p) a[j]=a[j-p];        a[0]+=p;        qq+=p;    }    ll ex=0;    if(n>a[0]) ex=(n-a[0])/p;    int q=(n-a[0])%p;    int mx;    fo(i,pos[t],pos[t]+q-1) a[++a[0]]=a[i],mx=max(mx,a[i]);    int cd=0;    fo(i,1,a[0])    {        int l=0,r=cd;        while(l+1<r)        {            int mid=(l+r)/2;            if(d[mid]<=a[i]) l=mid;            else r=mid;        }        int zz;        if(d[r]<=a[i]) zz=r;        else zz=l;        zz++;        d[zz]=a[i];        if(zz>cd) cd++;    }    printf("%lld",cd+ex);}
1 0
原创粉丝点击