zoukankan      html  css  js  c++  java
  • “Shopee杯” e起来编程暨武汉大学2020年大学生程序设计大赛(网络预选赛)

    A Monument For Heroes

    题意:

    给出n个字符串列表(长度不超过10),每个字符串只可以拼接在它前面的字串后面,且要求前面尾字母的字串与它的首字母相同,当拼接成一个字符串t后,要求t的首字母和尾字母相同,求可以拼接成的字符串t的最长长度。(1<=n<=2*10^5)

    思路:

    一直在想以每个字符串的首字母和尾字母作点连边,求一个有重边自环的最长路径环...其实就是一个线性DP啦,题解的做法很好,f[i][l][r]表示前i个字符串组成的左边字符是l,右边字符是r的最大长度。状态转移就是:当第i个串(l...r)时,f[i][j][r]=max(f[i-1][j][l]+w)。又是一类环形DP的做法

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    struct ac{
        int l,r,w;
    } node[N];;
    char str[20];
    int f[30][30];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
             scanf("%s",str);
             int w=strlen(str);
             node[i].w=w;
             node[i].l=str[0]-'a';
             node[i].r=str[w-1]-'a';
        }
        memset(f,-0x3f,sizeof f);
        for(int i=0;i<26;++i) f[i][i]=0;
        for(int i=1;i<=n;++i){
            for(int j=0;j<26;++j){
                int l=node[i].l,r=node[i].r,w=node[i].w;
                f[j][r]=max(f[j][r],f[j][l]+w);
            }
        }
        int res=0;
        for(int i=0;i<26;++i) res=max(res,f[i][i]);
        cout<<res<<endl;
        return 0;
    }
    

    B Best Match

    题意:

    给出一个序列,求有多少种互为相反数(0和自己互为相反数)的二元组合

    思路:

    用map记录一个数出现的次数,set将所有出现的数记录,循环set统计

    #include<bits/stdc++.h>
    using namespace std;
    set<int> S;
    map<int,int> mmp;
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;++i){
            int x;
            cin>>x;
            mmp[x]++;
            S.insert(x);
        }
        long long res=0;
        for(auto x: S){
            if(x==0) res+=(1ll*mmp[0]*(mmp[0]-1)/2>0?1ll*mmp[0]*(mmp[0]-1)/2:0);
            else
            res+=1ll*mmp[x]*mmp[-x];
            //cout<<x<<":"<<mmp[x]<<" "<<mmp[-x]<<endl;
            mmp[x]=mmp[-x]=0;
        }
        cout<<res<<endl;
        return 0;
    }
    

    D DIY Masks at Home

    题意:

    给出一个字母矩阵,找到只有一种字母的面积最大的正方形矩阵。矩阵(1≤n,m≤2000)

    思路:

    两种做法

    DP

    f[i,j]表示(i,j)作为正方形右下角的最大边长,只有当(i,j)和(i-1,j),(i,j-1),(i-1,j-1)相等时这个点才可以和左上方合并成一个更大的正方形,否则f[i,j]=1.(不容易想到用DP来做呀=_=)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2010;
    char g[N][N];
    int f[N][N],n,m;
    int main(){
        int T;
        cin>>T;
        while(T--){
            cin>>n>>m;
            int ans=0;
            memset(f,0,sizeof f);
            for(int i=1;i<=n;++i)   cin>>(g[i]+1);
            for(int i=1;i<=n;++i){
                for(int j=1;j<=m;++j){
                    if(g[i][j]==g[i-1][j]&&g[i][j]==g[i][j-1]&&g[i][j]==g[i-1][j-1]){
                        f[i][j]=min(f[i][j-1],min(f[i-1][j],f[i-1][j-1]))+1;
                    }
                    else f[i][j]=1;
                    ans=max(ans,f[i][j]);
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    
    二分

    首先预处理每个格子与自己相同且连续的最远的距离。二分枚举正方形边长l,先从列开始遍历,每一列从上到下记录连续最远距离大于l的长度是否大于l。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2010;
    char g[N][N];
    int x[N][N],y[N][N],n,m;
    bool check(int k){
        for(int j=1;j<=m;++j){
            int l=0;
            for(int i=1;i<=n;++i){
                if(x[i][j]-j+1>=k&&g[i-1][j]==g[i][j]) l++;
                else if(x[i][j]-j+1>=k) l=1;
                else l=0;
                if(l>=k) {
                    return true;
                }
            }
        }
        return false;
    }
    int main(){
        int T;
        cin>>T;
        while(T--){
            cin>>n>>m;
            for(int i=1;i<=n;++i)   cin>>(g[i]+1);
            for(int i=1;i<=n;++i){
                int l=1;
                for(int j=1;j<=m;++j)
                    if(g[i][j]!=g[i][l]){
                        for(int k=j-1;k>=l;--k)
                            x[i][k]=j-1;
                        l=j;
                    }
                for(int j=l;j<=m;++j) x[i][j]=m;
            }
            int l=1,r=2010,ans=1;
            while(l<=r){
                int mid=(l+r)/2;
                if(check(mid)){
                    ans=max(ans,mid);
                    l=mid+1;
                }
                else r=mid-1;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

    E Yu is a Brutal Creature

    题意:

    1~n种有多数i满足((i*i+1)%i=0)

    思路:

    可以发现只有(1*1+1=2%1=0),所以...

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        int cnt=0;
        for(int i=0;i<=10000;++i){
            if((1ll*i*i+1) %(i+1)==0){
                ++cnt;
                //cout<<i<<" "<<1ll*i*i+1<<" "<<cnt<<endl;
            }
        }
        int T;
        cin>>T;
        while(T--){
            long long n;
            cin>>n;
            if(n==0) cout<<0<<endl;
            else  cout<<n-1<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    android灭屏后调用binder通讯竟然影响了socket的POLL_OUT事件,怪事。
    B0宏
    从surfaceflinger历史变更谈截屏
    arm下dlsym返回的符号地址居然不是偶对齐的。
    SIGCHLD waitpid, 小心子进程结束事件被偷了
    root权限后,不要忘了还有selinux
    shell命令管道未读完阻塞了子进程,与等待其结束的父进程死"锁"。
    我对BP网络的简单的理解
    python 中的字符串格式化
    阿里云深度学习采坑记
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12688015.html
Copyright © 2011-2022 走看看