• 20190823考试反思


      这次考试CE了。

      原因是我改了一个longlong没编译,然后最后查出来的时候已经没时间了。

      不CE的话应该rk7左右。update:因为这个CE把我卡出了第一基房!!!!

      但是都是暴力分。

      T1:是一个规律题,给了5个样例,但我都没看出来,也是废了。我用背包A了

      这个题首先是一道比较屎的背包都能想到。

      但是转移会出错,原因在于:$f[j]|=f[(j-w[i]+k)%k]$这个东西转移顺序出问题了。

      解决办法就是一个转移循环k次。

      复杂度$O(nk^{2})$但是题目给了三个分档,k=100,k=1000,n,k=100000

      首先100的肯定可以。

      1000的就会出问题。但是有一个剪枝就是每次转移的时候转移完看看答案是否变化,如果不变化那么很显然就不用在循环接下来的保证正确性的k次循环。经过实测在100次左右答案就不在变化,复杂度可过。

      100000的nk就死了,那么没办法,n的循环不能省,但是k的循环……,我可以随机找一个容积更新,大概随机次数在200次之后就稳定了。所以。。。。。n*?似乎可过????

      数据貌似卡不了我复杂度,正解$O(nlogn)$,n极限在1e5,然后内层循环能循环250。。,因为他即使是构造的,但我仍是随机看人品更新的

      然后多交两次就A了。

      其实正确率还是蛮高的,在控制使n*k<=25000000的时候接近100%

      n*k<=10000000的时候交3次WA1次。

      

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    using namespace std;
    const int N=1000020;
    int w[N],a[N],f[N],cnt;
    long long rd()
    {
        long long s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    int main()
    {
        //freopen("math5.in","r",stdin);
        srand(unsigned(time(0)));
        int n=rd(),k=rd();
        for(int i=1;i<=n;i++) a[i]=rd();
        for(int i=1;i<=n;i++)
        {
            if(!f[a[i]%k])
            {
                f[a[i]%k]=1;
                w[++cnt]=a[i]%k;
            }
        }
        int ans=0;
        sort(w+1,w+cnt+1,greater<int>());
        if(n==1)
        {
            int gcd=a[1]%k;
            for(int i=1;i<=k;i++)
                f[1ll*gcd*i%k]=1;
            for(int i=0;i<k;i++)
                ans=ans+f[i];
            printf("%d
    ",ans);
            for(int i=0;i<k;i++)
                if(f[i]) printf("%d ",i);
            puts("");
            return 0;
            return 0;
        }
        if(k<=100)
        {
            for(int i=1;i<=cnt;i++)
            {
                for(int p=1;p<=k;p++)
                {
                    int sum=0;
                    for(int j=0;j<k;j++)
                    {
                        f[j]|=f[(j-w[i]+k)%k];
                        sum+=f[j];
                    }
                    if(ans==sum) break;
                    ans=max(ans,sum);
                }
            }
            printf("%d
    ",ans);
            for(int i=0;i<k;i++)
                if(f[i])printf("%d ",i);
            puts("");
            return 0;
        }
        else if(k<=1000)
        {
            for(int i=1;i<=cnt;i++)
            {
                for(int p=1;p<=k;p++)
                {
                    int sum=0;
                    for(int j=0;j<k;j++)
                    {
                        f[j]|=f[(j-w[i]+k)%k];
                        sum+=f[j];
                    }
                    if(sum==ans) break;
                    else ans=max(ans,sum);
                }
            }
            printf("%d
    ",ans);
            for(int i=0;i<k;i++)
                if(f[i])printf("%d ",i);
            puts("");
            return 0;
        }
        else
        {
            for(register int i=1;i<=cnt;++i)
            {
                for(register int p=1;p*cnt<=25000000;++p)
                {
                    const int j=rand()%k;
                    f[j]|=f[(j-w[i]+k)%k];
                }
            }
            for(register int i=0;i<k;i++) ans+=f[i];
            printf("%d
    ",ans);
            for(register int i=0;i<k;i++)
                if(f[i])printf("%d ",i);
            puts("");
            return 0;
        }
    }
    /*
    g++ -std=c++11 1.cpp -o 1
    ./1
    2 8
    4 12
    */
    View Code

      T2:我做这题头脑很屎。一开始打了$O(n^{3}m^{3})$的打法,只能过暴搜。

      然后硬是转成图论题topu强行降成$O(n^{2}m^{2})$以为A了。(事实上只是把DP之间问题和子问题的关系图建出来了)

      结果后来发现数据范围只能$O(nm)$可过。

      然后我就暴毙了,

      方程想复杂了。

      优化其实用4个树状数组维护拆开绝对值后的最大值就行了。

      但是发现不用树状数组决策不会更劣因为在求最大值。

      直接用变量。

      

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int N=4020;
    int a[N][N],b[N][N],la[N*N],n,m,tt,cnt;
    long long f[N][N],ans;
    struct node{int x,y;};
    struct bitar
    {
        long long bin[N][N];
        void add(int x,int y,long long w)
        {
            for(register int i=x;i<=n;i+=(i&-i))
                for(register int j=y;j<=m;j+=(j&-j))
                    bin[i][j]=max(bin[i][j],w);
        }
        long long ask(int x,int y)
        {
            long long sum=-0x7fffffff;
            for(register int i=x;i;i-=(i&-i))
                for(register int j=y;j;j-=(j&-j))
                    sum=max(sum,bin[i][j]);
            return sum;
        }
    }aw,dw,as,ds;
    int rd()
    {
        register int s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    int main()
    {
        //freopen("biology4.in","r",stdin);
        n=rd(),m=rd();
        int mini=0x7fffffff;
        for(register int i=1;i<=n;i++)
            for(register int j=1;j<=m;j++)
            {
                a[i][j]=rd();
                if(a[i][j])    la[++tt]=a[i][j];
            }
        sort(la+1,la+tt+1);
        int len=unique(la+1,la+tt+1)-la-1;
        vector<node> p[len+2];
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
            {
                int tmp=lower_bound(la+1,la+len+1,a[i][j])-la;
                p[tmp].push_back((node){i,j});
                b[i][j]=rd();
            }
        long long ask1=0,ask2=0,ask3=0,ask4=0;
        for(int t=1;t<=len;t++)
        {
            for(int k=0;k<p[t].size();k++)
            {
                int i=p[t][k].x,j=p[t][k].y;
                if(t==1) f[i][j]=b[i][j];
                else f[i][j]=max(f[i][j],max(max(ask1+i+j,ask2+i-j),max(ask3-i+j,ask4-i-j))+b[i][j]);
            }
            for(int k=0;k<p[t].size();k++)
            {
                int i=p[t][k].x,j=p[t][k].y;
                ask1=max(ask1,f[i][j]-i-j);ask2=max(ask2,f[i][j]-i+j);
                ask3=max(ask3,f[i][j]+i-j);ask4=max(ask4,f[i][j]+i+j);
                ans=max(ans,f[i][j]);
            }
        }
        printf("%lld
    ",ans);
    }
    /*
    g++ 1.cpp -o 1
    ./1
    3 3
    1 2 3
    4 5 6
    7 8 9
    7 8 9
    7 6 4
    2 10 8
    */
    View Code

      T3:我又不会异或。。。。

      第一问直接用桶存位即可。

      第二问用一个可持久化trie树维护区间中异或a的值>b的个数。

      和数位DP一样记忆化搜索即可。

      

    #include<iostream>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int mod=1e9+7;
    const int N=100020;
    int a[N],f[N][25],mac[30],rt[N],tt,stack[N],top,lm[N],rm[N];
    bool b[N],c[N];
    struct trie{int l,r,s;}tr[N*25];
    long long rd()
    {
        long long s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9'){if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    void build(int x,int &k,int len)
    {
        k=++tt;tr[k]=tr[x];
        if(len==0){tr[k].s++;return;}
        if(b[len]==0) build(tr[x].l,tr[k].l,len-1);
        else build(tr[x].r,tr[k].r,len-1);
        tr[k].s=tr[tr[k].l].s+tr[tr[k].r].s;
    }
    int dfs(int k,int len,int lim)
    {
        if(!k) return 0;
        if(!lim) return tr[k].s;
        if(len==0) return lim^1;
        long long ans=0;
        if((b[len]^0)>=c[len])ans=(ans+dfs(tr[k].l,len-1,lim&&((b[len]^0)==c[len])))%mod;
        if((b[len]^1)>=c[len]) ans=(ans+dfs(tr[k].r,len-1,lim&&((b[len]^1)==c[len])))%mod;
        return ans;
    }
    int main()
    {
        int n=rd(),opt=rd();long long ans1=0,ans2=0;mac[0]=1;
        for(int i=1;i<=25;i++) mac[i]=mac[i-1]<<1;
        for(int i=1;i<=n;i++) a[i]=rd();
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=22;j++) f[i][j]=f[i-1][j]+((a[i]&mac[j])!=0);
            for(int k=1,x=a[i];k<=22;k++,x>>=1) b[k]=(x&1);
            build(rt[i-1],rt[i],22);
        }
        a[0]=a[n+1]=0x7fffffff;
        for(int i=0;i<=n+1;i++)
        {
            while(top>0&&a[stack[top]]<a[i]) rm[stack[top]]=i,top--;
            stack[++top]=i;
        }top=0;
        for(int i=n+1;i>=0;i--)
        {
            while(top>0&&a[stack[top]]<=a[i]) lm[stack[top]]=i,top--;
            stack[++top]=i;
        }
        for(int i=1;i<=n;i++)
        {
            for(int k=1,x=a[i];k<=22;k++,x>>=1)c[k]=(x&1);
            if(i-lm[i]<rm[i]-i)
            {
                for(int j=lm[i]+1;j<=i;j++)
                {
                    for(int k=1,x=a[j];k<=22;k++,x>>=1) b[k]=(x&1);
                        ans2=(ans2+1ll*a[i]*(dfs(rt[rm[i]-1],22,1)-dfs(rt[i-1],22,1)+mod)%mod)%mod;
                    for(int k=0;k<=22;k++)
                    {
                        if(a[j]&mac[k])ans1=(ans1+1ll*a[i]*mac[k]%mod*(rm[i]-i+mod-(f[rm[i]-1][k]-f[i-1][k]+mod)%mod+mod)%mod)%mod;
                        else ans1=(ans1+1ll*a[i]*mac[k]%mod*(f[rm[i]-1][k]-f[i-1][k]+mod)%mod)%mod;
                    }
                }
            }
            else
            {
                for(int j=i;j<rm[i];j++)
                {
                    for(int k=1,x=a[j];k<=22;k++,x>>=1) b[k]=(x&1);
                        ans2=(ans2+1ll*a[i]*(dfs(rt[i],22,1)-dfs(rt[lm[i]],22,1)+mod)%mod)%mod;
                    for(int k=0;k<=22;k++)
                    {
                        if(a[j]&mac[k])ans1=(ans1+1ll*a[i]*mac[k]%mod*(i-lm[i]+mod-(f[i][k]-f[lm[i]][k]+mod)%mod+mod)%mod)%mod;
                        else ans1=(ans1+1ll*a[i]*mac[k]%mod*(f[i][k]-f[lm[i]][k]+mod)%mod)%mod;
                    }
                }
            }
        }
        if(opt==1) printf("%lld
    ",ans1);
        if(opt==2) printf("%lld
    ",ans2);
        if(opt==3) printf("%lld
    %lld
    ",ans1,ans2);
        return 0;
    }
    /*
    g++ -std=c++11 2.cpp -o 2
    ./2
    */
    View Code

      

  • 相关阅读:
    单位
    北京户口
    中科院助理工程师
    SQL学习
    question
    ROI选取过程
    IT学习网站
    撞库 拖库
    善用人类记忆的特点去高效学习
    为什么散步对健康很有益处
  • 原文地址:https://www.cnblogs.com/starsing/p/11417578.html
Copyright © 2020-2023  润新知