【天梯赛训练记录】GPLT 团体程序设计天梯赛训练1

训练情况

赛后反思

L2-2一道显然的树的父亲标识法,求树的深度,但是调了半天,写了记忆化还是超时丢了两分,L3-2是 DP,但是暴力枚举set去重拿满18分,后续还需要加强DP训练

L1-1

巨恶心的模拟题,一道需要特别注意换行和空格处理的问题,一队 10 人,我们按学校的顺序遍历,如果当前学校仍有队员则往下分配座位即可,我们需要另外记录一下上一个分配座位的学校,如果当前学校与上个学校相同需要隔座位,输出 10 个一组,注意行末空格和换行的问题,格式错误了好几发

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 103;

int n;
int a[N];
vector<int> ans[N];
int tot = 0;

signed main(){
    int sum = 0;
    cin>>n;
    for(int i = 1;i<=n;i++) cin>>a[i],a[i]*=10,sum+=a[i];
    int last = 0;
    int cnt = 10000;
    while(cnt--){
        for(int i = 1;i<=n;i++){
            if(a[i]){
                if(i == last) ++tot;
                ans[i].emplace_back(++tot);
                a[i]--;
                last = i;
            }
        }
    }
    for(int i = 1;i<=n;i++){
        cout<<"#"<<i<<endl;
        for(int j = 0;j<ans[i].size();j++){
            if(j%10==9) cout<<ans[i][j];
            else cout<<ans[i][j]<<" ";
            if(i == n && j == ans[i].size() - 1) return 0;
            if(j%10==9) cout<<endl;
        }
    }
	return 0;
}

L1-2

这题空间卡的很死,大力 DFS 枚举塞进数组里喜提空间超限,对于长度为 n 的字符串,显然有 \(26^n\) 种字符串,所以我们倒数第几个可以给它搞正过来,这题步长 1 的字符串可以等效转换为 26 进制,所以我们直接写个十进制转 26 进制即可,进制转换模板是 % 26 / 26,注意处理一下 0 对应的 a,while循环有些逆天情况会不输出 a

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;

signed main(){
	int a,b; cin>>a>>b;
	int ans = 1ll;
	for(int i = 1;i<=a;i++) ans*=26ll;
	b = ans - b;
	char c[100];
	int tot = 0;
	if(b == 0){
		for(int i = 1;i<=a;i++) cout<<"a";
		return 0;
	}
	while(b){
		c[++tot] = 'a'+(b%26ll);
		b/=26ll;
	}
    while(tot < a) c[++tot] = 'a';
	for(int i = tot;i;i--) cout<<c[i];
	return 0;
}

L1-3

白送题,8 折就是乘 0.8,答案就是两数相乘/10,再保留两位小数

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int main(){
    double a,b; cin>>a>>b;
    cout<<fixed<<setprecision(2)<<a*b/10<<endl;
	return 0;
}

L1-4

白送题,按照题目所述直接输出

点击查看代码
#include <bits/stdc++.h>

using namespace std;


int main(){
	cout<<"2018"<<endl;
	cout<<"wo3 men2 yao4 ying2 !"<<endl;
	return 0;
}

L1-5

白送题,计算 a+b,循环一下输出 Wang! 即可

点击查看代码
#include <bits/stdc++.h>

using namespace std;


int main(){
	int a,b; cin>>a>>b;
	for(int i = 1;i<=a+b;i++) cout<<"Wang!";
	return 0;
}

L1-6

白送题,显然颠倒的过程是上下对称,然后再左右对称,最后判断颠倒后是否相等即可,相等需要多输出一行,这题难在代码实现

点击查看代码
#include <bits/stdc++.h>

using namespace std;

const int N = 103;

string s[N];
string t[N];

int main(){
	char c; int n;
	cin>>c>>n;
	getchar();
	for(int i = 1;i<=n;i++){
		getline(cin,s[i]);
	}
	for(int i = 1;i<=n;i++){
		t[i] = s[n-i+1];
	}
	for(int i = 1;i<=n;i++){
		reverse(t[i].begin(),t[i].end());
	}
	bool flag = false;
	for(int i = 1;i<=n;i++) if(s[i] != t[i]) flag = true;
	if(flag){
		for(int i = 1;i<=n;i++){
			for(int j = 0;j<n;j++){
				if(t[i][j] == ' ') cout<<' ';
				else if(t[i][j] == '@') cout<<c; 
			}
			cout<<endl;
		}
	} else {
		cout<<"bu yong dao le"<<endl;
		for(int i = 1;i<=n;i++){
			for(int j = 0;j<n;j++){
				if(t[i][j] == ' ') cout<<' ';
				else if(t[i][j] == '@') cout<<c; 
			}
			cout<<endl;
		}
	}
	return 0;
}

L1-7

这题有个坑点,得到至少 1 名评委的认可,所以如果某个人都没得到评委认可,无论什么情况他都是输,需要多判断一下这个,其他直接模拟分数加的过程,最后判断哪个大输出哪个即可

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int main(){
	int a,b; cin>>a>>b;
	int acnt = 0,bcnt = 0;
	for(int i = 1;i<=3;i++){
		int x; cin>>x;
		if(x == 0) acnt++;
		else if(x == 1) bcnt++;
	}
	if(acnt == 0){
		cout<<"The winner is b: "<<b<<" + "<<bcnt<<endl;
		return 0;
	}
	if(bcnt == 0){
		cout<<"The winner is a: "<<a<<" + "<<acnt<<endl;
		return 0;
	}
	if(a>b) cout<<"The winner is a: "<<a<<" + "<<acnt<<endl;
	else cout<<"The winner is b: "<<b<<" + "<<bcnt<<endl;
	return 0;
}

L1-8

白送题,数列求和再求平均数再除二,最后数列遍历一遍,判断差的绝对值哪个更小更新答案即可

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int main(){
    int n; cin>>n;
    vector<string> a(n + 1);
    vector<int> b(n + 1);
    int sum = 0;
    for(int i = 1;i<=n;i++) cin>>a[i]>>b[i],sum+=b[i];
    sum /= n;
    sum /= 2;
    string ans;
    int now = INT_MAX;
    for(int i = 1;i<=n;i++){
        if(abs(b[i] - sum) < now){
            now = abs(b[i] - sum);
            ans = a[i];
        }
    }
    cout<<sum<<" "<<ans<<endl;
	return 0;
}

L2-1

并查集维护联通块,白送的并查集模板,对于打击掉的城市,我们使用标记一下,然后连边并查集维护联通的时候遇到有标记的直接跳过,最后判断每个点是否是孤立的(fa[x] = x)即可,我这边直接扔到 set 里面,判断联通块个数是否等于城市数

点击查看代码
#include <bits/stdc++.h>

using namespace std;

const int N = 1e4 + 3;

int fa[N];

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x);
    y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

int main(){
    int n,m; cin>>n>>m;
    vector<int> u(m + 1),v(m + 1);
    for(int i = 1;i<=m;i++) cin>>u[i]>>v[i];
    int q; cin>>q;
    while(q--){
        vector<bool> vis(n + 1);
        for(int i = 1;i<=n;i++) fa[i] = i;
        int k; cin>>k;
        for(int i = 1;i<=k;i++){
            int x; cin>>x;
            vis[x] = 1;
        }
        for(int i = 1;i<=m;i++){
            if(vis[u[i]] || vis[v[i]]) continue;
            Union(u[i],v[i]);
        }
        set<int> se;
        for(int i = 1;i<=n;i++) se.insert(Find(i));
        if(se.size() == n) cout<<"YES"<<endl;
        else cout<<"NO"<<endl; 
    }
	return 0;
}

L2-2

这道题我分数没有拿满,这题显然可以从子节点往父节点 x = fa[x] 暴力跳,同时记录每个点的深度,但是会被卡时间,顺带写了一手记忆化,记录当前位置的深度,如果遇到有计算过的直接加答案,不需要继续往上跳,多了一些些分

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int n; cin>>n;
    vector<int> a(n + 1);
    vector<int> dp(n + 1);
    vector<int> cnt(n + 1);
    for(int i = 1;i<=n;i++) cin>>a[i];
    for(int i = 1;i<=n;i++){
        int x = a[i];
        int now = 0;
        while(x != -1){
            if(!cnt[x]) now++;
            else {
                now += cnt[x]+1;
                break;
            }
            x = a[x];
        }
        cnt[i] = now;
    }
    int ma = 0;
    for(int i = 1;i<=n;i++){
        ma = max(ma,cnt[i]);
    }
    vector<int> ans;
    cout<<ma+1<<endl;
    for(int i = 1;i<=n;i++) if(ma == cnt[i]) ans.emplace_back(i);
    for(int i = 0;i<ans.size();i++){
        if(i == ans.size()-1) cout<<ans[i];
        else cout<<ans[i]<<" ";
    }
    return 0;
}

L2-3

这题金额计算比较简单,满足条件的直接按照题目所述加上去即可,难在排序取排名的情况,特别是并列的情况,我们考虑使用桶排序,把分数全部扔进桶里,使用一个变量记录当前分数对应的排名,最后从大到小遍历,遇到有至少一个的排名+1,记录完之后再加上桶里面分数的个数,这样处理并列的问题

点击查看代码
#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 3;

int n,g,k;

int tong[103];

struct node{
    string a;
    int b;
}a[N];

bool cmp(node x,node y){
    if(x.b == y.b) return x.a < y.a;
    else return x.b > y.b;
}

int main(){
    cin>>n>>g>>k;
    int ans = 0;
    for(int i = 1;i<=n;i++){
        cin>>a[i].a>>a[i].b;
        if(a[i].b >= g && a[i].b <= 100) ans += 50;
        else if(a[i].b >= 60 && a[i].b < g) ans += 20;
    }
    sort(a + 1,a + 1 + n,cmp);
    for(int i = 1;i<=n;i++){
        tong[a[i].b]++;
    }
    map<int,int> rk;
    int now = 0;
    for(int i = 100;~i;i--){
        if(tong[i]){
            now++;
            rk[i] = now;
            now += tong[i]-1;
        }
    }
    cout<<ans<<endl;
    int i = 1;
    while(i<=n && rk[a[i].b] <= k){
        cout<<rk[a[i].b]<<" "<<a[i].a<<" "<<a[i].b<<endl;
        i++;
    }
    return 0;
}

L2-4

这题不会,直接瞪眼,发现一个样例答案刚好是最后两个数,随手试一发,输出最后两个数,意外拿了两分,稳赚不亏

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int n,m;

int main(){
    cin>>n>>m;
    getchar();
    for(int i = 1;i<=m;i++){
        string s; cin>>s;
        getline(cin,s);
    }
    int a,b; cin>>a>>b;
    cout<<a<<" "<<b<<endl;
    return 0;
}

L3-2

显然去重的问题扔给set,我们考虑枚举删哪个点,我们直接暴力 \(O(n^4)\) 模拟,枚举删掉三个点的位置,插入到 set 里面去重,直接输出集合大小即可,这题正解是 DP ,但我不会

点击查看代码
#include <bits/stdc++.h>

using namespace std;

set<string> se;

int main(){
    string s; cin>>s;
    int n = s.size();
    se.insert(s);
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            for(int k = 0;k<n;k++){
                string ss;
                for(int l = 0;l<n;l++){
                    if(l == i || l == j || l == k) continue;
                    ss += s[l];
                }
                se.insert(ss);
            }
        }
    }
    // for(auto i:se){
    //     cout<<i<<endl;
    // }
    cout<<se.size()<<endl;
	return 0;
}

L3-3

题目里说三点贡献答案是 0.000,测试点里应该会有这种情况,直接无脑输出 0.000,水了两分,稳赚不亏

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int main(){
    cout<<"0.000";
    return 0;
}
posted @   MNNUACM_2024ZY  阅读(106)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示