zoukankan      html  css  js  c++  java
  • 20191011

    前言

    • 最近考试考得最差的一次吧。
    • 考试的时候太浮躁了,T2题都读错。
    • 其实读错题没什么,主要是T1连对拍都不打,于是一些非常智障的错误导致本应AC的代码变成WA0。
    • 以后考试有时间的话对拍还是尽量题题都打……

    T1

    • 这场考试也挺奇怪的,我感觉T1应该是三个题里最难的。
    • 考试的时候刚开始一直觉得直接快速幂就行,但后来发现需要考虑行间关系,便很自然的想到正解。
    • 可以把%n后结果相同的列一起考虑,这样可以进行dp
    • 设f[i][j]表示考虑了%n结果不大于i的所有列,一共放了j个棋子的方案数。
    • 则$f[i][j]=sumlimits_{k=max(0,j-n)}^j f[i-1][j-k]*{{C_n^k}^{m/n+[m\%n>=i]}}$
    • 显然可以滚动。
    • 然后我就滚动不清空,爆零两行泪了……
    • ${C_n^k}^{m/n+[m\%n>=i]}$这个东西可以预处理的。
    • 所以时间复杂度为$Theta(N^4)$,空间复杂度$Theta(N^2)$。
    • 注意有(应该有,我不确定)m<n的情况。
    #include<cstdio>
    using namespace std;
    int const N=10002,M=102,mod=1e9+7;
    long long fac[N],inv[N];
    long long cp[M];
    long long f[2][N];
    int cf[M];
    long long cq[M][2];
    inline long long power(long long x,long long y){
        long long ans=1;
        for(;y;y>>=1,x=x*x%mod)
            if(y&1)ans=ans*x%mod;
        return ans;
    }
    inline long long C(int x,int y){
        return fac[x]*inv[y]%mod*inv[x-y]%mod;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    int main(){
        //freopen("3.in","r",stdin);
        //freopen("6.out","w",stdout);
        int n,c;
        long long m;
        scanf("%d%lld%d",&n,&m,&c);
        int lit=n*n,hh=m%n,pc=(m/n)%(mod-1);
        fac[0]=1;
        for(register int i=1;i<=lit;++i)fac[i]=fac[i-1]*i%mod;
        inv[lit]=power(fac[lit],mod-2);
        for(register int i=lit;i;--i)inv[i-1]=inv[i]*i%mod;
        for(register int i=0;i<=n;++i)cp[i]=C(n,i);
        for(register int i=1;i<=hh;++i)cf[i]=1;
        for(register int i=0;i<=n;++i)
            cq[i][0]=power(cp[i],pc),cq[i][1]=cq[i][0]*cp[i]%mod;
        int u=0,v=1;
        f[0][0]=1;
        if(m<n){
            for(register int i=1;i<=m;++i,u=v,v^=1)
                for(register int j=0;j<=c;++j){
                    f[v][j]=0;
                    for(register int k=max(0,j-n);k<=j;++k)
                        f[v][j]=(f[v][j]+cq[j-k][1]*f[u][k])%mod;
                }
            printf("%lld",f[u][c]);
            return 0;
        }
        for(register int i=1;i<=n;++i,u=v,v^=1)
            for(register int j=0;j<=c;++j){
                f[v][j]=0;
                for(register int k=max(0,j-n);k<=j;++k)
                    f[v][j]=(f[v][j]+cq[j-k][cf[i]]*f[u][k])%mod;
            }
        printf("%lld",f[u][c]);
        return 0;
    }
    View Code

    T2

    • 考试看成最长不下降子串,当场去世……
    • 题意是只要左端点最小右端点最大就行,中间元素可不单调。
    • 考虑从右向左扫描,维护一个单调不上升的栈。
    • 把栈内元素当作右端点,维护栈内元素的左端点即可。
    • 具体实现不是很好描述,请自行脑补(不行就颓码吧)。
    • 时空复杂度$Theta(N)$
    • 本题1e7的读入量,使用fread可以快3倍以上。
    #include<cstdio>
    #define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
    using namespace std;
    int const N=1e7+5,L=2e8;
    char buf[L],*S,*T;
    inline int read(){
        int ss(0);char bb(getchar());
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    inline int min(int x,int y){
        return x<y?x:y;
    }
    int a[N],stk[N],mx[N],top,ans=1;
    int pos[N];
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        int n=read();
        a[0]=1e9+7;
        for(register int i=1;i<=n;++i)a[i]=read();
        for(register int i=n,x;i;--i){
            x=a[i];
            while(x>a[stk[top]]){
                ans=max(ans,stk[top]-pos[top]+1);
                if(top^1 && mx[top-1]>=a[pos[top]])pos[top-1]=pos[top];
                mx[top-1]=min(mx[top-1],mx[top]),--top;
            }
            stk[++top]=i;
            pos[top]=i,mx[top]=a[i];
        }
        while(a[0]>a[stk[top]]){
            ans=max(ans,stk[top]-pos[top]+1);
            if(top^1 && mx[top-1]>=a[pos[top]])pos[top-1]=pos[top];
            mx[top-1]=min(mx[top-1],mx[top]),--top;
        }
        printf("%d",ans);
        return 0;
    }
    /*5
    3 8 7 5 9  
    */
    View Code

    T3

    • 没什么好说的,原题,同permu。
    • 才知道当时打的是回滚莫队……当时颓的题解也没说啊
    • 时间复杂度$Theta(Nsqrt{N})$,空间复杂度$Theta(N)$。
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int const N=1e5+5;
    inline int read(){
        int ss(0);char bb(getchar());
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    int n,m;
    int a[N],stk[N],top;
    int as[N];
    struct node{
        int l,r,id;
    }q[N];
    int bl[N],rb[N];
    int bar[N],le[N],re[N];
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        n=read(),m=read();
        int bk=sqrt(n),ct=n/bk,ln=0,rn=0;
        for(register int i=1;i<=ct;++i){
            ln=rn+1,rn+=bk;
            rb[i]=rn;
            for(register int j=ln;j<=rn;++j)bl[j]=i;
        }
        if(rn<n){
            rb[++ct]=n;
            for(register int j=rn+1;j<=n;++j)bl[j]=ct;
        }
        for(register int i=1;i<=n;++i)a[i]=read();
        for(register int i=1;i<=m;++i)q[i].l=read(),q[i].r=read(),q[i].id=i;
        sort(q+1,q+m+1,[](node skyh,node yxs){
            return (bl[skyh.l]^bl[yxs.l])?skyh.l<yxs.l:skyh.r<yxs.r;
        });
        for(register int i=1,ans,tans,z;i<=m;++i){
            if(bl[q[i].l]^bl[q[i-1].l]){
                memset(bar,0,sizeof(bar));
                memset(le,0,sizeof(le));
                memset(re,0,sizeof(re));
                rn=rb[bl[q[i].l]];
                ans=tans=0;
            }
            //printf("%d %d %d
    ",q[i].l,q[i].r,rb[bl[q[i].l]]);
            if(q[i].r<=rb[bl[q[i].l]]){
                for(register int j=q[i].r;j>=q[i].l;--j){
                    ++bar[stk[++top]=z=a[j]];
                    if(bar[z-1]&&bar[z+1])
                        le[re[le[z-1]]=re[z]=re[z+1]]=le[z]=le[z-1];
                    else if(bar[z-1])re[le[z]=le[z-1]]=re[z]=z;
                    else if(bar[z+1])le[re[z]=re[z+1]]=le[z]=z;
                    else le[z]=re[z]=z;
                    tans=max(tans,re[z]-le[z]+1);
                }
                while(top){
                    z=stk[top--];
                    if(le[z]^z)re[le[z]]=z-1;
                    if(re[z]^z)le[re[z]]=z+1;
                    le[z]=re[z]=0,--bar[z];
                }
                as[q[i].id]=tans,tans=0;
                continue;
            }
            //printf("%d ",rn);
            while(rn<q[i].r){
                ++bar[z=a[++rn]];
                if(bar[z-1]&&bar[z+1])
                    le[re[le[z-1]]=re[z]=re[z+1]]=le[z]=le[z-1];
                else if(bar[z-1])re[le[z]=le[z-1]]=re[z]=z;
                else if(bar[z+1])le[re[z]=re[z+1]]=le[z]=z;
                else le[z]=re[z]=z;
                ans=max(ans,re[z]-le[z]+1);
                //printf("!!%d %d %d %d
    ",ans,z,re[z],le[z]);
            }//printf("%d
    ",ans);
            tans=ans;
            for(register int j=rb[bl[q[i].l]];j>=q[i].l;--j){
                ++bar[stk[++top]=z=a[j]];
                if(bar[z-1]&&bar[z+1])
                    le[re[le[z-1]]=re[z]=re[z+1]]=le[z]=le[z-1];
                else if(bar[z-1])re[le[z]=le[z-1]]=re[z]=z;
                else if(bar[z+1])le[re[z]=re[z+1]]=le[z]=z;
                else le[z]=re[z]=z;
                tans=max(tans,re[z]-le[z]+1);
                //printf("%d %d
    ",tans,z);
            }
            while(top){
                z=stk[top--];
                if(le[z]^z)re[le[z]]=z-1;
                if(re[z]^z)le[re[z]]=z+1;
                le[z]=re[z]=0,--bar[z];
            }
            as[q[i].id]=tans;
        }
        for(register int i=1;i<=m;++i)printf("%d
    ",as[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    会计基础第二次模拟题(4)
    会计基础第二次模拟题(3)
    会计基础第二次模拟题(2)
    如何使用印象笔记进行更好的学习呢?
    怎么安装WinXP和Win7双系统
    清理和关闭多余的Windows 7系统服务
    Foxmail邮箱最新应用指南二
    Windows 系统提示“内存不足”的原因及解决方法
    会计基础第二次模拟试题(1)
    关于后端程序开发如何评估工作量的方法
  • 原文地址:https://www.cnblogs.com/remarkable/p/11658197.html
Copyright © 2011-2022 走看看