LYU2023.4.2周赛题解

本文提供了四道编程题的解题思路,涉及精度处理、贪心策略、动态规划以及广度优先搜索等算法。第一题解决大数精度问题,第二题采用贪心方法分配椅子,第三题使用动态规划优化椅子借用,第四题通过BFS解决兔子跳跃问题,最后一题利用位运算找出最长的共性位。
摘要由CSDN通过智能技术生成


a+b

由于sqrt函数求平方根在求大数的时候会有精度问题,可以用二分或者将函数求出的结果判断一下,才能获得正确答案。


#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int N=2e5+10,INF=0x3f3f3f3f,mod=998244353;

void solve()
{
	int a,b; cin>>a>>b;
	int m=1e12;
	int s=a*m+b*m-1;
	int ans=sqrt(s);
	if(ans*ans>s) ans--;
	cout<<ans<<"\n";
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t=1; cin>>t;
	while(t--)
	{
		solve();
	}

	return 0;
}

借椅子Ⅰ

贪心


#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int N=2e5+10,INF=0x3f3f3f3f3f3f3f3f,mod=998244353;
PII p[N];//存放每个实验室的距离和椅子数量 
int v[N];//存放取完之后只剩一个椅子的实验室的距离 

void solve()
{
	int n,m,k; cin>>n>>m>>k;
	int s=0;//去别的实验室总共可以获得的椅子数量
	 
	for(int i=1;i<=n;i++)
	{
		int a,b; cin>>a>>b;
		
		//b放在前面,因为后面对p数组排序是根据第一个关键字排序的 
		p[i]={b,a};
		s+=a;
	}
	
	//如果所有的椅子加起来都不够,输出-1 
	if(s+m<k)
	{
		cout<<"-1\n"; return ;
	}
	
	int sum=k-m;//存还需要多少椅子
	//如果不缺椅子,输出0 
	if(sum<=0)
	{
		cout<<"0\n"; return ;
	}
	
	sort(p+1,p+1+n);
	int l=0,r=0;
	
	int ans=0;//存答案
	 
	for(int i=1;i<=n;i++)
	{
		int d=p[i].x,cnt=p[i].y;//d表示这个实验室的距离,cnt表示这个实验室具有的椅子数量 
		
		//如果前面用完但是还剩一个椅子的实验室大于两个,就要判断
		//前面两个实验室分别单独取更优,还是在当前实验室取两个椅子更优 
		while(r-l>=2 and v[l]+v[l+1]<=d)
		{
			ans+=v[l]+v[l+1];
			l+=2;
			sum-=2;
		}
		
		//看当前实验室的椅子需要多少个两次才能取完 ,并且不超过需要的椅子 
		int t=min(sum/2,cnt/2);
		ans+=t*d;
		sum-=t*2;
		cnt-=t*2;
	
		if(!sum) break;
		//如果最后该实验室还剩一个椅子,那么就加到v里面 
		if(cnt)
		{
			v[r++]=d;
		}
	}
	//如果最后还缺一个椅子,那么从v头去一个就行,因为我们先放进去的是距离最短的 
	if(sum) ans+=v[l];
	//来回所以乘以2 
	cout<<ans*2<<"\n"; 
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t=1; //cin>>t;
	while(t--)
	{
		solve();
	}

	return 0;
}

借椅子Ⅱ

dp

#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int N=2e5+10,INF=0x3f3f3f3f3f3f3f3f,mod=998244353;
PII p[N];//存放每个实验室的距离和椅子数量 
int dp[1010][2222];//dp[i][j]表示在前i个实验室中取,椅子总和大于等于j所需要的最短距离 

void solve()
{
	int n,m,k; cin>>n>>m>>k;
	int s=0;//去别的实验室总共可以获得的椅子数量
	 
	for(int i=1;i<=n;i++)
	{
		int a,b; cin>>a>>b;
		
		//b放在前面,因为后面对p数组排序是根据第一个关键字排序的 
		p[i]={b,a};
		s+=a;
	}
	
	//如果所有的椅子加起来都不够,输出-1 
	if(s+m<k)
	{
		cout<<"-1\n"; return ;
	}
	
	int sum=k-m;//存还需要多少椅子
	//如果不缺椅子,输出0 
	if(sum<=0)
	{
		cout<<"0\n"; return ;
	}
	//初始化 
	memset(dp,0x3f,sizeof dp);
	
	for(int i=0;i<=m;i++) dp[0][i]=0;//m个椅子都不需要到别的实验室去借 
	
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=k;j++)
		{
			dp[i][j]=min(dp[i-1][j],dp[i-1][max((int)0,j-p[i].y)]+p[i].x);
		}
	}
	
	
	
	
	cout<<dp[n][k]*2<<"\n"; 
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t=1; //cin>>t;
	while(t--)
	{
		solve();
	}

	return 0;
}

兔子

BFS模板题


代码如下:

#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int N=3333,INF=0x3f3f3f3f3f3f3f3f,mod=998244353;
int n,m,k;
int g[N][N];//存桌子每一处的高度 
int stx,sty;//起始位置 
int d[N][N];//记录到这一点的最短距离 
//8个方向 
int dir[8][2]={{0,1},{1,0},{-1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};

void solve()
{
	cin>>n>>m>>k; cin>>stx>>sty;
	
	for(int i=1;i<=n+2;i++)
	{
		for(int j=1;j<=m+2;j++) cin>>g[i][j];
	}
	
	//为了方便判断,这里从起始位置到起始位置的距离置为1,
	//这样d[x][y]==0表示这个点还没记录 
	d[stx][sty]=1;
	
	//BFS
	queue<PII> q;
	q.push({stx,sty});
	
	
	while(q.size())
	{
		auto t=q.front(); q.pop();
		//枚举8个方向 
		for(int i=0;i<8;i++)
		{
			//求出每个方向新的x,y 
			int x=t.x+dir[i][0],y=t.y+dir[i][1];
			
			//如果这个点之前算过,那么他的最短距离已经知道了
			//或者两点的距离超过k,那么兔子跳不到这个点 
			if(d[x][y] || abs(g[t.x][t.y]-g[x][y])>k) continue;
			
			//如果它到达边界了,那么一定是最短的答案 
			if(x==1||x==n+2||y==1||y==m+2)
			{
				cout<<d[t.x][t.y]; return;
			}
			d[x][y]=d[t.x][t.y]+1;
			q.push({x,y});
		}
	}
	//上面每个点都遍历了但是没有答案,那么不能到达输出-1 
	cout<<"-1\n";
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t=1; //cin>>t;
	while(t--)
	{
		solve();
	}

	return 0;
}

最长的&

位运算


#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int N=2e5+10,INF=0x3f3f3f3f3f3f3f3f,mod=998244353;
int mp[50];//存放二进制位置i为1的数的个数 
int a[N];

void solve()
{
	int n; cin>>n;
	memset(mp,0,sizeof mp);
	int ans=0;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		int xx=a[i];
		for(int j=0;j<=32;j++)
		{
			if((xx>>j)&1) mp[j]++;ans=max(ans,mp[j]);
		}
	}
	
	cout<<ans<<"\n";
}

signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	int t=1; //cin>>t;
	while(t--)
	{
		solve();
	}

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值