新春马拉松题解

~ 2025-2-12 10:27:34

重点说一下能做的 44 道题目吧,题解顺序是按照出题人认为的难度写的。

另外 44 道题目其实是给提高组学生准备的,提高组学生可以上课听我讲解。

然后由于第 55 个题有些同学使用 AIAI 软件通过了,所以就也顺便说下,但是的的确确根本就不是你们现在能做的,不过确实偏板子,所以被 AIAI 识破了。本道题就不给代码了(因为没有意义,发了也看不懂)

寻找题目位置

题解

这个题目应该不难,第一个问题就是 /100/100 向上取整,第二个问题就是 %100+1100+1

标程

int n;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    cout << n / 100 + 1 << " " << (n % 100) + 1;
    return 0;
}

寻找lzp

题解

应该也不难,但是使用了最低计分可能卡掉了一些学生。

做法就是先找到 ll,然后沿着 88 个方向找到 zz 确定了方向后,沿着这个方向看看有没有 pp 就行了。记得在寻找过程中数组下标是否越界。

标程

int dx[8] = {0, 0, 1, 1, 1, -1, -1, -1};
int dy[8] = {1, -1, 1, 0, -1, 1, 0, -1};
int n, ans;
char mapp[30][30];
int ok(int x, int y, int fx)
{
    int xx = x + dx[fx];
    int yy = y + dy[fx];
    if(xx >= 1 && xx <= n && yy >= 1 && yy <= n)
    {
        if(mapp[xx][yy] == 'p')
        {
            return 1;
        }
    }
    return 0;
}
int check(int x, int y)
{
    int res = 0;
    for(int i = 0; i < 8; i++)
    {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if(xx >= 1 && xx <= n && yy >= 1 && yy <= n)
        {
            if(mapp[xx][yy] == 'z')
            {
                res += ok(xx, yy, i);
            }
        }
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            cin >> mapp[i][j];
        }
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(mapp[i][j] == 'l')
            {
                ans += check(i, j);
            }
        }
    }
    cout << ans << '\n';
    return 0;
}

数数几个P

题解

这个只是一个单纯的大模拟,没对的同学我只能归结为懒+模拟能力有待提升。

模拟思路就是先找那个矩形,然后四个方向看看有没有竖着的就行了。

题目中给了很多的数据,自己编一些例子也并不难,很容易测出代码哪里出了问题。

标程

#include <bits/stdc++.h>
using namespace std;
int n;
char a[30][30];

bool f(int x,int y,int lenx,int leny){
	int tx=x+lenx-1,ty=y+leny-1;
	int cnt=0;//.的数目
	int lx=100,ly=100,rx=0,ry=0;
	for(int i=x;i<=tx;i++){
		for(int j=y;j<=ty;j++){
			if(i==x||j==y||i==tx||j==ty){
				if(a[i][j]!='*') return false;
			}else{
				if(a[i][j]=='.'){
					cnt++;
					lx=min(lx,i);
					ly=min(ly,j);
					rx=max(rx,i);
					ry=max(ry,j);
				}
			}
		} 
	}
	if(cnt!=(rx-lx+1)*(ry-ly+1)){
		return false;
	} 
	return true;
}


bool check(int x,int y,int lenx,int leny){
	int tx=x+lenx-1,ty=y+leny-1;
	//tx ty lenx leny
	//上行旗杆 
	if(a[x-1][y]=='*'){
		for(int i=x;i<=tx;i++) if(a[i][y-1]=='*'||a[i][ty+1]=='*') return false; //左右列 
		for(int i=y;i<=ty;i++) if(a[tx+1][i]=='*') return false;//下行 
		//矩形 四边 sx,fx, sy,fy
		int sx=x-1,fx=x-1,sy=y,fy=y;
		while(a[sx-1][y]=='*') sx--;
		while(a[x-1][sy-1]=='*') sy--;
		while(a[x-1][fy+1]=='*') fy++;
		if(sy<y&&fy>ty) return false;
		if(fy-sy+1<=leny) return false;
		for(int i=sx;i<=fx;i++){
			for(int j=sy;j<=fy;j++){
				if(i==sx&&a[i-1][j]=='*') return false;
				if(i==fx&&(j<y||j>ty)&&a[i+1][j]=='*') return false;
				if(j==sy&&a[i][j-1]=='*') return false;
				if(j==fy&&a[i][j+1]=='*') return false;
				if(a[i][j]!='*') return false;
			}
		}
		return true;
	}
	//下行旗杆 
	if(a[tx+1][y]=='*'){
		for(int i=x;i<=tx;i++) if(a[i][y-1]=='*'||a[i][ty+1]=='*') return false; //左右列 
		for(int i=y;i<=ty;i++) if(a[x-1][i]=='*') return false;//上行 
		//矩形 四边 sx,fx, sy,fy
		int sx=tx+1,fx=tx+1,sy=y,fy=y;
		while(a[fx+1][y]=='*') fx++;
		while(a[tx+1][sy-1]=='*') sy--;
		while(a[tx+1][fy+1]=='*') fy++;
		if(sy<y&&fy>ty) return false;
		if(fy-sy+1<=leny) return false;
		for(int i=sx;i<=fx;i++){
			for(int j=sy;j<=fy;j++){
				if(i==sx&&(j<y||j>ty)&&a[i-1][j]=='*') return false;
				if(i==fx&&a[i+1][j]=='*') return false;
				if(j==sy&&a[i][j-1]=='*') return false;
				if(j==fy&&a[i][j+1]=='*') return false;
				if(a[i][j]!='*') return false;
			}
		}
		return true;
	}
	//左行旗杆 
	if(a[x][y-1]=='*'){
		
		for(int i=x;i<=tx;i++) if(a[i][ty+1]=='*') return false; //右列 
		for(int i=y;i<=ty;i++) if(a[x-1][i]=='*'||a[tx+1][i]=='*') return false;//上下行 
		//矩形 四边 sx,fx, sy,fy
		int sx=x,fx=x,sy=y-1,fy=y-1;
		while(a[sx-1][y-1]=='*') sx--;
		while(a[fx+1][y-1]=='*') fx++;
		while(a[x][sy-1]=='*') sy--; 
		if(sx<x&&fx>tx) return false;
		if(fx-sx+1<=lenx) return false; 
		
		for(int i=sx;i<=fx;i++){
			for(int j=sy;j<=fy;j++){
				if(i==sx&&a[i-1][j]=='*') return false;
				if(i==fx&&a[i+1][j]=='*') return false;
				if(j==sy&&a[i][j-1]=='*') return false;
				if(j==fy&&(i<x||i>tx)&&a[i][j+1]=='*') return false;
				if(a[i][j]!='*') return false;
			}
		}
		return true;
	}
	//右行旗杆 
	if(a[x][ty+1]=='*'){
		for(int i=x;i<=tx;i++) if(a[i][y-1]=='*') return false; //左列 
		for(int i=y;i<=ty;i++) if(a[x-1][i]=='*'||a[tx+1][i]=='*') return false;//上下行 
		//矩形 四边 sx,fx, sy,fy
		int sx=x,fx=x,sy=ty+1,fy=ty+1;
		while(a[sx-1][ty+1]=='*') sx--;
		while(a[fx+1][ty+1]=='*') fx++;
		while(a[x][fy+1]=='*') fy++; 
		if(sx<x&&fx>tx) return false;
		if(fx-sx+1<=lenx) return false; 
		for(int i=sx;i<=fx;i++){
			for(int j=sy;j<=fy;j++){
				if(i==sx&&a[i-1][j]=='*') return false;
				if(i==fx&&a[i+1][j]=='*') return false;
				if(j==sy&&(i<x||i>tx)&&a[i][j-1]=='*') return false;
				if(j==fy&&a[i][j+1]=='*') return false;
				if(a[i][j]!='*') return false;
			}
		}
		return true;	
	} 
	return false;
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
		}
	}
//	cout<<f(1,2,3,4);
	int c=0;
	for(int i=1;i<n;i++){
		for(int j=1;j<n;j++){
			for(int lenx=3;i+lenx-1<=n;lenx++){
				for(int leny=3;j+leny-1<=n;leny++){
					if(f(i,j,lenx,leny)){
						if(check(i,j,lenx,leny)){
							//cout<<i<<" "<<j<<" "<<lenx<<" "<<leny<<endl; 	
							c++;
						}
					}
				}
			}
		}
	}
	cout<<c;
}

TooYoung的诅咒2.0

题解

首先,随机移动的意思是:

对于任意一个点而言,若以它为起点的边有 xx 个( xx00 则不会继续移动),那么这x条边每条边被移动到的概率都是(这个点被移动到个概率 (1/x)*(1/x))。

对于任意一个点而言,它的被移动到的概率是所有以它为终点的边被移动到的概率的和。

因为是一个有向无环图,所以可以参考拓扑排序的入度思想。

拓扑排序可以为我们提供一个完全有序的 O(n)O(n) 的搜索方式。

起点的被移动到的概率是 11

之后可以缩图使入度为 00 的点只有起点之后再按拓扑序遍历,也可以直接按照拓扑序遍历。

遍历时注意,深度为 00 的点即使有以它为起点的边也是不能继续移动的。

最后遍历一遍所有点,将深度为 00 的点的被移动到的概率加和,就是所求的概率。

标程

int n, m, s, deep[maxn], ru[maxn], cnt[maxn];
vector<int>G[maxn];
double ans[maxn], ANS;
queue<int>q;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m >> s;
    for(int i = 1; i <= n; i++)
        cin >> deep[i];
    for(int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if(deep[x] == 0) continue;
        G[x].push_back(y);
        cnt[x]++;
        ru[y]++;
    }
    for(int i = 1; i <= n; i++)
    {
        if(ru[i] == 0 && i != s)
        {
            q.push(i);
        }
    }
    while(q.empty() == 0)
    {
        int now = q.front(); q.pop();
        int siz = (int)G[now].size();
        for(int i = 0 ; i < siz; i++)
        {
            int nxt = G[now][i];
            ru[nxt]--;
            if(ru[nxt] == 0 && nxt != s)
                q.push(nxt);
        }
    }
    q.push(s);
    ans[s] = 10000;
    while(q.empty() == 0)
    {
        int now = q.front(); q.pop();
        int siz = (int)G[now].size();
        for(int i = 0 ; i < siz; i++)
        {
            int nxt = G[now][i];
            ans[nxt] += ans[now] / cnt[now];
            ru[nxt]--;
            if(ru[nxt] == 0) q.push(nxt);
        }
    }
    for(int i = 1; i <= n; i++)
    {
        if(deep[i] == 0) ANS += ans[i];
    }
    if(ANS >= 5000) cout << "YES\n";
    else cout << "NO\n";
    return 0;
}

趣味二维数组

题解

这个就是前面所说的第 55 题,学过二分图的同学不难发现,这显然是一个二分图问题,那么二分答案再二分图判断一下就行了。



我们会审查剪贴板内容,并对发布不合适内容的同学进行相应的处理