“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;
}
原文地址:https://www.cnblogs.com/jjl0229/p/12688015.html