2024初三年前集训测试1

前言

  • 总分: \(210\)

    \(T1\) : \(40\) ,挂了 \(60\) ,没考虑到他最后可能没有 “句号”

    \(T2\)\(100\)\(Hash\)\(map\) \(A\) 掉了,直接用 \(map\) 实际上也能过。

    \(T3\)\(70\) ,忘记判断无解挂了 \(20\) 。跑的最短路,发现会被 \(Hack\) 调了好久,到最后自己造的 \(Hack\) 也没有过,交上去只 \(Hack\) 掉一个,还可以。

    \(T4\)\(0\) ,读错题了,也是因为时间不够了,调 \(T3\) 时间用太长了,也没有想到用差分。

  • 比赛链接

题解

学说话

  • 题目链接

  • 题面:

    给出一句话,求其中最长一个单词的长度,每个单词用 \(\_\) 连接。

    \(eg: I\_am\_Charlie\) ,最长长度为 \(7\)

  • 解法:

    签到题,非常简单,但是挂分了,还是考虑不全面。

    注意他最后一个单词后可能没有 \(\_\) ,所以循环结束后还需要刷新答案,显然最后一个单词最长的都挂了。

  • 代码如下:

#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
using namespace std;
const int N=1e6+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=1;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
string s;
int n,ans,sum;
signed main()
{
    // #ifndef ONLINE_JUDGE
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // #endif
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
    cin>>s;
    n=s.size();
    for(int i=0;i<n;i++)
    {
        if(s[i]!='_') sum++;
        else 
            ans=max(ans,sum),
            sum=0;
    }
    ans=max(ans,sum);//这里不要忘了!qwq
    cout<<ans;
}

膜拜大佬

  • 题目链接

  • 题面:

    给出几个大佬的名字,判断接下来给出的几个名字是否是大佬。

  • 解法:

    \(Hash\) 一道,但数据足够水,直接 \(map\) 也能过。

    \(Hash\) 被卡掉,可能会想到字典树,但这玩意太容易 \(MLE\) 了开小了又会 \(RE\) ,所以尽可能别用吧。

    也可以再使用 \(map\) 存一下 \(Hash\) 值,这样匹配的时候可以把一个 \(n→ log\) ,但这样我为什么不直接用 \(map\) 呢?

  • \(Hash\) 代码:

#include<bits/stdc++.h>
#define int unsigned long long 
#define endl '\n'
using namespace std;
const int N=5010,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=1;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
string s,s1,s2;
int n,big,h,b[N],m;
map<int,bool>v;
void Base(int n)
{
    b[1]=233;
    for(int i=2;i<=n;i++)
        b[i]=b[i-1]*b[1];
}
int get_hash(string s)
{
    int l=s.size(),res=0;
    for(int i=0;i<l;i++)
        res=res*b[1]+s[i];
    return res;
}
signed main()
{
    // #ifndef ONLINE_JUDGE
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // #endif
    freopen("dalao.in","r",stdin);
    freopen("dalao.out","w",stdout);
    Base(N-1);
    read(n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        big=get_hash(s);
        v[big]=1;
    }
    read(m);
    for(int i=1;i<=m;i++)
    {
        cin>>s1>>s2>>s;
        h=get_hash(s);
        if(v[h]) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

走迷宫

  • 题目链接

  • 题面:

    迷宫起点 \(@\) 终点 \(=\)\(\#\) 表示墙,字母 \(A\sim Z\) 为传送门,成对出现,到达其中一传送门 立马 传到相同字母的另一装置上,传送过程不花费时间,剩下的是 \(\huge{.}\) ;从起点开始,可以上下左右走,每走一步为 \(1\) 秒。

    求最短多久可以到达终点。

  • 解法:

    赛时打了半天,相当麻烦,还 \(Hack\) 一个点,主要在于他到达传送门后立刻到达对应点,不可继续往前走,这对于我的代码就需要判断是进传送门还是出传送门,十分麻烦,而且不完全正确。

    听完同学的讲解后恍然大悟。

    难点在于建图,他到达这个传送点后立即传送。当前点 \(x\) 上下左右存在传送门,不放直接把 \(x\) 和传送终点连上,不连这个起点。

    如图:

    image

    image

    边权都是 \(1\)

    然后正常 \(spfa\) 最短路即可(当然 \(dijsktra\) 也可以)。

    至于建图时我用了一个比较巧妙的方法,用了一下 \(Hash\) 思想,存二维的 \(i,j\) 显然麻烦,将 \(i,j\) 放在一起转化成一个进制数,再来存图,就会方便很多。

    当然进制要选择要个大于 \(i,j\) 的质数,我选的 \(773\) ,最大搞出来才 \(2e5\) 左右,不用模数,就更没有误差。

    \(h=i\times 773+j\) ,用 \(h\) 来存。

  • 代码如下:

#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
using namespace std;
const int N=5e5+10,P=1e9+7,b=773;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=1;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
char a[510][510];
int n,m,sta,d[N],en,from[N],too[N];
bool v[N];
int head[N],to[N],w[N],nxt[N],tot;
queue<int>q;
int c[4]={1,-1,0,0},e[4]={0,0,1,-1};
void add(int x,int y,int z)
{
    nxt[++tot]=head[x];
    to[tot]=y;
    w[tot]=z;
    head[x]=tot;
}
void spfa(int x)
{
    memset(d,0x3f,sizeof(d));
    d[x]=0;
    v[x]=1;
    q.push(x);
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        v[x]=0;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i],z=w[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                if(!v[y])
                {
                    v[y]=1;
                    q.push(y);
                }
            }
        }
    }
}
signed main()
{
    // #ifndef ONLINE_JUDGE
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // #endif
    freopen("maze.in","r",stdin);
    freopen("maze.out","w",stdout);
    read(n),read(m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
            int h=i*b+j;
            if(a[i][j]=='@') sta=h;
            else if(a[i][j]=='=') en=h;
            else if(a[i][j]>='A'&&a[i][j]<='Z')
            {
                if(!from[a[i][j]-'A'+1])
                    from[a[i][j]-'A'+1]=h;
                else too[a[i][j]-'A'+1]=h;
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int h=i*b+j;
            if(a[i][j]!='#')
                for(int k=0;k<4;k++)
                {
                    int x=i+c[k],y=j+e[k];
                    int hh=x*b+y;
                    if(x>=1&&x<=n&&y<=m&&y>=1)
                    {
                        if(a[x][y]>='A'&&a[x][y]<='Z')
                        {
                            if(from[a[x][y]-'A'+1]!=hh)
                                add(h,from[a[x][y]-'A'+1],1);
                                
                            else add(h,too[a[x][y]-'A'+1],1);
                        }
                        else if(a[x][y]!='#')
                            add(h,hh,1);
                    }
                }
            
        }
    spfa(sta);
    if(d[en]>999999) cout<<-1;//记得判无解!!!qwq
    else cout<<d[en];
}
  • 附录:

    • 没用了的的 \(Hack\) 数据呈上(自造):

      \(C.@.C=\)\(C...@.C=\)

    • 关于测试点数据:

      37 70
      ######################################################################
      #....#TCP#...........................................................#
      #....#####.....#......#..............................................#
      #.............#.#....#.#.............................................#
      #..............######W#..............................................#
      #.............#........#..##############################.............#
      #............#..V....V..#..#............................#..#...#.....#
      #.............#........#....#............................#..#.#.#....#
      #.............#..X##X..#..#...............W...............#..#...#...#
      #............#...N##N...#..#.............................#...........#
      #........MOO..#..@.....#....#.#.#.#...................#.#............#
      #..............########.....#.#.#.##############.#.#..#.#............#
      #...........................#.#.#.#.............#.#.#.#.#............#
      #.......#########...........#.#.#.#.................#.#.#............#
      #......#.........#..........#.#.#.#.................#.#.#............#
      #..#.#.#G#R#A#S#S#.#.#......#.#.#.#.................#.#I#............#
      #..###################......#T#C#P#.................#I#G#............#
      #............................#.#.#...................#.#.............#
      #....................................................................#
      #....................................................................#
      #......########........########.......#...........#...........#......#
      #.....#...............#R......A#.......#.........#.#.........#.......#
      #.....#...............#........#........#.......#...#.......#........#
      #.....#...............#........#.........#.....#.....#.....#.........#
      #.....#...............#........#..........#...#.......#...#..........#
      #.....#...............#..M.....#...........#.#.........#.#...........#
      #......########........########.............#...........#............#
      #....................................................................#
      #....................................................................#
      #....................................................................#
      ####################################################################.#
      #....................................................................#
      ##.###################################################################
      #..#F#ZD#.#Y#.#JL#.#...#QJ#.#.#.#.#EK#....#.L#.............#BQ#......#
      #.##Z####.#U#.####.#.#.####.#.#.#.####.#..####.............####.####.#
      #....#DE#.###.#UH#...#.#HK#.#.#.#.#F...#........................#BY#.#
      ####################################################################=#
      

鸭子游戏

  • 题目链接

  • 关于原题:IncDec Sequence

  • 题面(原题):

    给定一个长度为 \(n\) 的数列 \(a_1\sim a_n\) ,每次可以选定一个区间 \([l,r]\) ,使这个区间内每个数都 \(+1\)\(-1\)

    先给定这个数列,求最少操作多少次能使其所有书都一样,在最少操作次数前提下,最终得到的数列会有多少中可能情况。

  • 解法:

    差分

    这是第二次模拟赛有差分不会了,看来我需要系统搞一下差分了。

    到最后数列内所有数都相同,也就是说,将其转化为差分数组 \(c_1\sim c_n\) ,那么除 \(c_1=a_1\) 外,\(c_2\sim c_n\) 军为 \(0\)

    线将原来的数组转化为差分数组。线选择一个区间 \([l,r]+1\) ,在差分数组中表示出来就是 \(c_l+1,c_{r+1}-1\) ,反之同理,运用差分的基本维护方法。那么现在在原数组中任意选择区间 \([l,r]\) ,转化在差分数组中就是任选两个数 \(+1\)\(-1\)

    我们当然要将差分数组中对应负值 \(+1\) ,对应 正值 \(-1\) ,那么每次修改就是选一出一组正负值,分别 \(-1,+1\)

    但同时也要考虑边界,我们的目标是将 \(c_2\sim c_n\) 都变为 \(0\) ,所以变 \(c_1\) 是没用的,同样的,变 \(c_{n+1}\) 也是没用的,所以尽可能的在 \(c_2\sim c_n\) 中选出一组正负值,直到最后只剩正值或负值,再去和 \(c_1,c_{n+1}\) 进行修改。

    那么按照上面的思路,用 \(q\) 表示 \(c_2\sim c_n\) 的正值的和,同理 \(p\) 表示负值的和,每次选出一组来就是进行 \(min(p,q)\) 步,到了最后只剩 \(p\) 或只剩 \(q\) 了,再将其和 \(c_1||c_{n+1}\) 进行组合,就再进行了 \(|p-q|\) 步。加在一起,也就是 \(max(p,q)\) 步,步数就这么解决了。

    那么继续考虑最后有多少种可能,最后 \(a_1\sim a_n\) 数组所有值都是一样的,而 \(c_1=a_1\) ,就是求到最后 \(c_1\) 有多少中可能情况。

    我们发现在前面的操作中和 \(c_1,c_{n+1}\) 都没有关系,直到最后 \(|p-q|\) 步,这几步可以任意选择和 \(c_1\)\(c_{n+1}\) 组合,那么从全部和 \(c_{n+1}\) 组合到全部和 \(c_1\) 组合,一共有 \(|p-q|+1\) 种情况,即最后的答案。

  • 代码如下:

#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
using namespace std;
const int N=2e6+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=1;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
int n,a[N],b[N],ans1,ans2;
signed main()
{
	#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif    
    read(n);
    for(int i=1;i<=n;i++)
    {
        read(a[i]);
        b[i]=a[i]-a[i-1];
        if(i>1)
        {
            if(b[i]>0) ans1+=b[i];
            else ans2-=b[i];
        }
    }
    cout<<max(ans1,ans2)<<endl<<abs(ans1-ans2)+1;
}

总结:

教练说这次题相对比较简单,下次考就难了,还有下次?

总体下来确实难度不大,但不妨碍我分数不高。

也是有一定收获的,入门晚,快速赶进度的局限性显然使我必定会有很多地方不扎实,经验也较少,每一次比赛的挂分其实都是依次教训,都是为今后不再犯这样的错误作为一次教训。每次比赛发现有不扎实的地方就回去复习,收货不小。

集训时间好短啊,再过几天就走了,但短短几天收获非常的大,光是这种教训就吃了好多次,都是为了以后的真正比赛不出这种低级错误做准备。

所以我有必要去好好搞一下差分了。

也是有一些巧妙的做法,自己想出来的有用 \(Hash\) 将二维变为一个值方便储存;别人讲解的,尤其是那个建图,非常的巧妙,当然也是自己画了个图方便理解;差分的做法一直那么巧妙。

posted @ 2024-01-31 16:59  卡布叻_周深  阅读(36)  评论(0)    收藏  举报