2023HFOI小学组 题解

发布时间 2023-12-10 19:59:07作者: shimingxin1007

2023HFOI小学组 题解

存钱(saving)

题目传送门

前置芝士:数学

很明显,数据范围过大,考虑用周期性来解决。

周一至周日节省的钱数相同,很明显是一个周期。

算出来所有周期,再把剩下来的天数节省的钱累加。

/*Written by smx*/
#include<bits/stdc++.h>
using namespace std;
long long num[10];
int main()
{
	freopen("saving.in","r",stdin);
	freopen("saving.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	long long a,b,c,ans=0;
	cin>>a>>b>>c;
	ans=c/(a*5+b*2)*7;
	c=c%(a*5+b*2);
	num[1]=num[2]=num[3]=num[4]=num[5]=a;
	num[6]=num[7]=b;
	for(int i=1;i<=7&&c>0;i++)
	{
		ans++;
		c=c-num[i];
	}
	cout<<ans;
	return 0;
}

逆波兰式计算(rpn)

题目传送门

前置芝士:数组,栈,后缀表达式

很明显就是一个后缀表达式,考虑使用栈解决,偷懒用STL

可以使用 stringstreamstoi 进行读入,标记 +- 出现的位置,模拟即可。

/*Written by smx*/
#include<bits/stdc++.h>
using namespace std;
int n;
int a[105];
stack<int> s;
int main()
{
	freopen("rpn.in","r",stdin);
	freopen("rpn.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		string t;
		cin>>t;
		if(t=="+")
		{
			a[i]=-1;
		}
		else if(t=="-")
		{
			a[i]=-2;
		}
		else
		{
			stringstream sin;
			sin.clear();
			sin<<t;
			sin>>a[i];
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(a[i]>0)
		{
			s.push(a[i]);
		}
		else
		{
			int x,y;
			x=s.top();
			s.pop();
			y=s.top();
			s.pop();
			if(a[i]==-1)
			{
				s.push(x+y);
			}
			else
			{
				s.push(y-x);
			}
		}
	}
	cout<<s.top();
	return 0;
}

自动驾驶(autopilot)

题目传送门

前置芝士:映射,数组连续性

将所有子串存入数组,找出是否出现多次。

考虑map思想,但是map常数大,考虑使用简单的数组连续性。

/*Written by smx*/
#include<bits/stdc++.h>
using namespace std;
string a[1000005];
int main()
{
	freopen("autopilot.in","r",stdin);
	freopen("autopilot.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,k,ans=0,m=0;
	string s;
	cin>>n>>k>>s;
	for(int i=0;i<n-k+1;i++)
	{
		string str;
		str=s.substr(i,k);
		a[++m]=str;
	}
	sort(a+1,a+m+1);
	int flag=0;
	for(int i=1;i<=m;i++)
	{
		if(a[i]==a[i+1])
		{
			flag=1;
		}
		else
		{
			if(flag==1)
				ans++;
			flag=0;
		}
	}
	cout<<ans+flag;
	return 0;
}

K 阶恒星系(kgalaxy)

题目传送门

前置芝士:优先队列

讨论 pi 左边是否满足条件,右边同理。

动态地维护 k 个元素,频繁查询、删除最大值,和插入一个元素,很明显用优先队列(大根堆)即可。

/*Written by smx*/
#include<bits/stdc++.h>
using namespace std;
priority_queue<int> ql;
priority_queue<int> qr;
int a[1000005],f[1000005];
int main()
{
	freopen("kgalaxy.in","r",stdin);
	freopen("kgalaxy.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,k,ans=0;
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];	
	}
	for(int i=1;i<=n;i++)
	{
		if(ql.size()<k)
		{
			ql.push(a[i]);
		}
		else
		{
			if(ql.top()>a[i])
			{
				ql.pop();
				ql.push(a[i]);
			}
			if(ql.top()<a[i])
			{
				f[i]=1;
			}
		}
	}
	for(int i=n;i>=1;i--)
	{
		if(qr.size()<k)
		{
			qr.push(a[i]);
		}
		else
		{
			if(qr.top()>a[i])
			{
				qr.pop();
				qr.push(a[i]);
			}
			if(qr.top()<a[i])
			{
				if(f[i]==1)
				ans++;
			}
		}
	}
	cout<<ans;
	return 0;
}