天梯赛省赛选拔赛复盘

很可惜的一场比赛,两小时调H题没调出来T_T,如果调出来就能被选上了。无限Sad(意难平,希望蓝桥杯不留遗憾。



A题:蜗牛与井 签到

在这里插入图片描述

虽然是签到还wa了两发,有被自己菜到qwq

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read() 
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}

ll h,x,y;

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>h>>x>>y;
	ll n=x-y;
	ll sum=x,ans=1;
	ll tmp=h-sum;
	if(tmp%n==0)	ans+=tmp/n;
	else ans+=tmp/n+1;
	cout<<ans;
	return 0; 
}


B题:火力覆盖 贪心+数学

在这里插入图片描述

从右端点不断向左枚举,每次找到最靠右的没有被炸弹炸到的点,可以考虑递归

我的代码

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}
const int N=1e6+5;

int n;
int ans[N],vis[N];
int cnt;
stack<int> s;

void find(int n){
	if(s.size()==0)	return;
	int pos=n;
	while(double(1.2*pos)>=double(n))	pos--;
	pos++;
	ans[++cnt]=pos;
	//cout<<pos<<endl;
	for(int i=ceil(0.8*pos);i<=min(n,int(1.2*pos));i++)
		s.pop();
	int x=ceil(0.8*pos)-1;
	if(x<1)	return;
	else find(x);
}

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)	s.push(i);
	find(n);
	cout<<cnt<<endl;
	for(int i=1;i<=cnt;i++)	cout<<ans[i]<<" ";
	return 0; 
}

标程

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;cin>>n;
    vector<int> ans;
    int r=n;
    for(int i=n;i>=0;--i){
        if(i*1.2<r){
            ans.push_back(i+1);
            r=ceil((i+1)*0.8)-1;
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();++i)cout<<ans[i]<<" ";
    cout<<endl;
}

C题:ZZ的函数

待补

D题:自然溢出 思维+数学

在这里插入图片描述

刚开始一眼没看出来,于是自己手搓了几组数组发现了规律,当n=66时刚好模数为0

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

unsigned long long fac(unsigned long long x){
    unsigned long long ans=1;
    if(x>=66)	return 0;
    for(unsigned long long i=1;i<=x;i++){
        ans*=i;
    }
    return ans;
}

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	ull n;
	cin>>n;
	cout<<fac(n);
	return 0; 
}

E题:小y的棋子

挖坑待补

F题:小y的镜像串

挖坑待补

G题:飞,比跑快吧

挖坑待补

H题:旋转矩阵 思维+模拟

在这里插入图片描述

到了无限sad的题,赛时的思路是发现n数据量很小(n<=4),只需要重点讨论n=4的情况即可,于是考虑用数组存下每一列的最大值,然后遍历所给矩阵找到每个数出现的位置及次数,觉得只有当v[0]==v[1]&&v[2]==v[3]时情况比较特殊,然后开始暴力枚举特殊情况,最后就g了……(不知道哪里错了

正解:因为只有n(n<=4)行,所以会有n个行最大值,即最多有n个有效列(最少有一个即所有最大值都在一列的时候),这时候我们可以对列最大值排序,取出前n大的列再暴力枚举,这样的时间复杂度为O(n^(n+1))可过。

赛时的代码(以为很对,然而只过了10%的数据:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}

int t;
int a[5][110];

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>t;
	while(t--){
		int n,m;
		cin>>n>>m;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				cin>>a[i][j];
			}
		}
		vector<int> mx(m);
		mx.clear();
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++)
				mx[i]=max(mx[i],a[j][i]);
		}
		vector<int> v;
		map<int,vector<PII>> mp;
		v.clear();
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				if(a[j][i]==mx[i]){
					v.push_back(mx[i]);
					mp[mx[i]].push_back({j,i});
				}
			}
		}
		sort(v.begin(),v.end(),greater<int>());
		ll ans=0;
		if(n<=3){
			for(int i=0;i<n;i++)	ans+=v[i];
		}else {
			if(v[0]==v[1]&&v[2]==v[3]){
				int ok=0;
				vector<int> s1; s1.clear();
				set<int> st1; st1.clear();
				for(auto x:mp[v[0]]){
					s1.push_back(x.fi);
					st1.insert(x.se);
				}
				vector<int> s2; s2.clear();
				set<int> st2; st2.clear();
				for(auto x:mp[v[2]]){
					s2.push_back(x.fi);
					st2.insert(x.se);
				}
				
				if(s1.size()==2&&s2.size()==2&&st1.size()==1&&st2.size()==1){
					if((s1[0]+1==s1[1])||(s1[0]==0&&s1[1]==3)){
						if(s2[0]+2==s2[1]) ok=1;
					}else {
						if((s2[0]+1==s2[1])||(s2[0]==0&&s2[1]==3))	ok=1;
					}
				}
				if(ok==1)	ans=v[0]+v[1]+v[2]+v[4];
				else ans=v[0]+v[1]+v[2]+v[3];
			}
			else ans=v[0]+v[1]+v[2]+v[3];
		}
		cout<<ans<<endl;
	}
	return 0; 
}

标程没看太懂(附上某巨巨好懂的代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
#define int long long
int g[10][200];
tuple<int,int,int>maxv[10];
void solve()
{
    memset(maxv,0,sizeof maxv);
    int n,m;
    cin>>n>>m;
    vector<int>q;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
             cin>>g[i][j],q.push_back(g[i][j]);
    sort(q.begin(),q.end(),greater<int>());
    if(n<=3||n==4&&q[3]==q[4])
    {
        int res=0;
        for(int i=0;i<n;i++)res+=q[i];
        cout<<res<<'\n';
        return ;
    }
    int res=0;
    map<int,int>mp;
    for(int i=0;i<n;i++)mp[q[i]]=1,res+=q[i];//mp标记前n个最大值
    
    map<int,int>y;
    vector<int>x[110];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(mp[g[i][j]])
            {
                y[j]=1;//y=1表示第j列存在前n个最大值
                x[j].push_back(i);//存第j列最大值的行号
            }
        }
    }
    if(y.size()==2)//当且仅当只有两列有最大值的情况
    {
        map<int,int>st;
        for(auto [a,b] : y)
        {
            int xx=x[a][1]-x[a][0];//行号差
            st[xx]=1;
        }
        if(st.count(1)&&st.count(2))res=res-q[3]+q[4];//当且仅当行号差为1和2即此时无论怎么旋转矩阵,总有第二个最大值被第一个最大值挡住,只能往后取q[4]
    }
    cout<<res<<'\n';
}

signed main()
{
	int T;cin>>T;
    while(T--)solve();
}

I题:抽卡游戏

挖坑待补

J题:可莉的宝藏

挖坑待补

K题:回文时刻 模拟

在这里插入图片描述

比较经典的回文串判定、字符串处理问题

我的极其冗长的代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}

string s;

bool check(string str){
	int len=str.size();
	int flag=1;
	int l=0,r=len-1;
	while(l<=r){
		if(str[l]==str[r]){
			l++;
			r--;
		}else {
			flag=0;
			break;
		}
	}
	return flag;
}

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>s;
	string hh=s.substr(0,2);
	string mm=s.substr(3,2);
	string ss=s.substr(6,2);
	//cout<<hh<<mm<<ss;
	int a=(hh[0]-'0')*10+hh[1]-'0';
	int b=(mm[0]-'0')*10+mm[1]-'0';
	int c=(ss[0]-'0')*10+ss[1]-'0';
	for(int k=c+1;k<60;k++){
		string s="";
		if(a<10)	s+='0';
		s+=to_string(a);
		if(b<10)	s+='0';
		s+=to_string(b);
		if(k<10)	s+='0';
		s+=to_string(k);
		if(check(s)){
			if(a<10)	cout<<'0';
			cout<<a<<':';
			if(b<10)	cout<<'0';
			cout<<b<<':';
			if(k<10)	cout<<'0';
			cout<<k;
			return 0;
		}
	}
	for(int i=b+1;i<60;i++){
		for(int j=0;j<60;j++){
			string s="";
			if(a<10)	s+='0';
			s+=to_string(a);
			if(i<10)	s+='0';
			s+=to_string(i);
			if(j<10)	s+='0';
			s+=to_string(j);
			if(check(s)){
				if(a<10)	cout<<'0';
				cout<<a<<':';
				if(i<10)	cout<<'0';
				cout<<i<<':';
				if(j<10)	cout<<'0';
				cout<<j;
				return 0;
			}
		}
	}
	for(int i=(a+1)%24;i<24;i++){
		for(int j=0;j<60;j++){
			for(int k=0;k<60;k++){
				string s="";
				if(i<10)	s+='0';
				s+=to_string(i);
				if(j<10)	s+='0';
				s+=to_string(j);
				if(k<10)	s+='0';
				s+=to_string(k);
				if(check(s)){
					if(i<10)	cout<<'0';
					cout<<i<<':';
					if(j<10)	cout<<'0';
					cout<<j<<':';
					if(k<10)	cout<<'0';
					cout<<k;
					return 0;
				}
			}
		}
	}
	return 0; 
}

题解十分简洁的代码:

#include<bits/stdc++.h>
using namespace std;
int a,b,c;
bool check1(int x,int y){
    int a1=x%10,a2=x/10;
    int b1=y%10,b2=y/10;
    return a1==b2&&b1==a2;
}
bool check2(int x){
    int a1=x%10,a2=x/10;
    return a1==a2;
}
int main(){
    scanf("%d:%d:%d",&a,&b,&c);
    int f=0;
    for(int i=0;i<24;i++){
        for(int j=0;j<60;j++){
            for(int k=0;k<60;k++){
                if(check1(i,k)&&check2(j)){
                    if(i>a||i==a&&j>b||i==a&&j==b&&k>c){
                        printf("%02d:%02d:%02d\n",i,j,k);
                        return 0;
                    }
                }
            }
        }
    }
    printf("00:00:00\n");
    return 0;
}

L题:hs爱矩形 模拟

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define endl '\n'
typedef long long ll;
typedef pair<int,int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}

int x[3],y[3];
map<int,int> mp1,mp2;

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	for(int i=1;i<=3;i++){
		cin>>x[i]>>y[i];
		mp1[x[i]]++;
		mp2[y[i]]++;
	}
	for(auto i:mp1){
		if(i.se==1)	cout<<i.fi<<" ";
	}
	for(auto i:mp2){
		if(i.se==1)	cout<<i.fi;
	}
	return 0; 
}


M题:ZZ的图灵奖

挖坑待补

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值