• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
nannandbk
博客园    首页    新随笔    联系   管理    订阅  订阅
AtCoder Beginner Contest 308 ABCDEF

AtCoder Beginner Contest 308

A - New Scheme

Problem Statement

题意:给你8个数,如果满足以下条件输出Yes,否则输出No

条件:

  1. 单调不减
  2. 大小在100到675之间
  3. 都是25的倍数

Solution

按照题意判断即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll last = 0;

int main()
{
	bool ok = true;
	for(int i = 1;i<=8;i++)
	{
		string s;
		cin>>s;
		if(s.size()>3)ok = false;
		ll x = stol(s);
		if(x>675||x<100)ok = false;
		if(x%25)ok = false;
		if(x<last)ok = false;
		last = x;
	}
	if(ok)cout<<"Yes\n";
	else cout<<"No\n";
	return 0;
}

B - Default Price

Problem Statement

题意:给你N个串,代表不同的颜色,再给你M个串,对于M个价格,如果上述N个串中有M个中没出现过的,那价值就是p0.问你价格是多少。

Solution

思路:模拟,用map映射一下就ok

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 110;
int n,m;
map<string,int>mp;
string s[N],t[N];
int price;
int main()
{
	cin>>n>>m;
	for(int i = 1;i<=n;i++)
		cin>>s[i];
	for(int i = 1;i<=m;i++)
		cin>>t[i];
	int p0;
	cin>>p0;
	for(int i = 1;i<=m;i++)
	{
		int p;
		cin>>p;
		mp[t[i]] = p;
	}
	ll ans = 0;
	for(int i = 1;i<=n;i++)
	{
		if(mp[s[i]])ans+=mp[s[i]];
		else ans += p0;
	}
	cout<<ans<<endl;
	return 0;
}

C - Standings

Problem Statement

题意:给你N组\(A_i\)和\(B_i\),用\(\dfrac{Ai}{Ai+Bi}\)表示胜率。问胜率按从大到小排的结果。

Solution

思路:之间用小数算会有精度问题,我们对柿子变形一下。

\(\dfrac{A_i}{A_i+B_i}>\dfrac{A_j}{A_j+B_j}\)

\(A_i*(A_j+B_j)>A_j*(A_i+B_i)\)

用long long记录,判断即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
array<ll,3>v[N];
bool cmp(array<ll,3>a,array<ll,3>b)
{
	if(a[0]*(b[0]+b[1])!=b[0]*(a[0]+a[1]))return a[0]*(b[0]+b[1])>b[0]*(a[0]+a[1]);
	else return a[2]<b[2];
}
int main()
{
	int n;
	cin>>n;
	for(int i = 1;i<=n;i++)
	{
		ll a,b;
		cin>>a>>b;
		v[i] = {a,b,i};
	}	
	sort(v+1,v+1+n,cmp);
	for(int i = 1;i<=n;i++)
	{
		cout<<v[i][2]<<" ";
	}
	cout<<endl;
	return 0;
}

D - Snuke Maze

Problem Statement

题意:起点是(1,1),终点是(n,m),问你存不存在从(1,1)走到(n,m)都是"snuke"的循环的一条路径呢?

Solution

思路:\(dfs\)搜,注意\(vis\)数组不用回溯,因为这条路不能走,换个方向肯定也是不行的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N  = 510;
int n,m;
char a[N][N];
int dir[5][2]={{1,0},{0,1},{0,-1},{-1,0}};
string s = "snuke";
bool ok;
bool in(int x,int y)
{
	return x>=1&&x<=n&&y>=1&&y<=m;
}
bool vis[N][N];
void dfs(int x,int y,int cur)
{
	if(ok)return;
	if(x==n&&y==m)
	{
		ok = true;
		return;
	}
	for(int i = 0;i<4;i++)
	{
		int dx = x+dir[i][0],dy = y+dir[i][1];
		if(in(dx,dy)&&a[dx][dy] == s[(cur+1)%5]&&!vis[dx][dy])
		{
			vis[dx][dy] = true;
			dfs(dx,dy,(cur+1)%5);
		}
	}
}


int main()
{
	cin>>n>>m;
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	}
	if(a[1][1]!='s')
	{
		cout<<"No\n";
		return 0;
	}
	vis[1][1] = true;
	dfs(1,1,0);
	if(ok)cout<<"Yes\n";
	else cout<<"No\n";
	return 0;
}

E - MEX

Problem Statement

题意:给你一个长度为N的串S,由MEX三种字母组成

找到所有的\((i,j,k)\)满足\((A_i,A_j,A_k)\)是MEX的,求他们的\(mex\)的和。

\(mex\)表示没出现过的最小非负整数。

Solution

思路:前缀和思想。

直接枚举肯定是不行的,复杂度太高了。

我们可以对M进行分类,按类别计数。

\(cntl[i][0\)~\(2]\)表示前缀的前\(i\)个有多少个M = 0,M = 1,M = 2的

同理对X统计后缀:

\(cntr[i][0\)~\(2]\)表示后缀的后\(i\)个有多少个X = 0,X = 1,X = 2的

按照上述操作,接下来我们只需要考虑E。

我们枚举E,用\(mex\)函数算值,设E的位置是\(pos\),那么我们用\(cntl[pos-1][0\)~ \(2]*cntr[pos+1][0\)~\(2]*1*mex\)

注意不要爆int,开long long。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
int a[N];
string s;
int cntl[N][3],cntr[N][3];
ll res;
int mex(int i,int j,int k)
{
	int ans = 0;
	if(i==0||j==0||k==0)
	{
		ans++;
		if(i == 1||j==1||k==1)
		{
			ans++;
			if(i == 2||j==2||k==2)
			{
				ans++;
			}
		}
	}
	return ans;
}
int main()
{
	int n;
	cin>>n;
	for(int i = 1;i<=n;i++)
		cin>>a[i];
	cin>>s;
	s ="?"+s;
	for(int i = 1;i<=n;i++)
	{
		if(s[i]=='M')
			cntl[i][a[i]]++;
		for(int j = 0;j<3;j++)
			cntl[i][j] += cntl[i-1][j];
	}
	if(s[n]=='X')cntr[n][a[n]]++;
	for(int i = n-1;i>1;i--)
	{
		if(s[i]=='X')
			cntr[i][a[i]]++;
		for(int j = 0;j<3;j++)
			cntr[i][j] += cntr[i+1][j];
	}

	for(int i = 2;i<n;i++)
	{
		if(s[i]!='E')continue;
		for(int j = 0;j<3;j++)
		{
			for(int k = 0;k<3;k++)
			{
				res += 1ll*cntl[i-1][j]*cntr[i+1][k]*mex(j,a[i],k);
			}
		}
	}
	cout<<res<<endl;
	return 0;
}

F - Vouchers

Problem Statement

思路:\(N\)种商品,对应价格是\(P。有M个优惠券,满\)\(L_i\)减\(D_i\)

问你怎么买最便宜?

Solution

思路:贪心。能优惠就优惠。用set 的 lower_bound二分,找到第一个大于等于限制\(L_i\)的\(P_i\),当然优惠券要按优惠力度排序先。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
ll p[N],sum;
bool vis[N];
map<ll,int>cnt;
set<ll>s;
struct ty
{
	ll l,d;
}a[N];
bool cmp(ty a,ty b)
{
	return a.d>b.d;
}
main()
{
	int n,m;
	cin>>n>>m;
	for(int i = 1;i<=n;i++)
	{
		int x;
		cin>>x;
		cnt[x]++;
		s.insert(x);
		sum += x;
	}
	for(int i = 1;i<=m;i++)
		cin>>a[i].l;
	for(int i = 1;i<=m;i++)
		cin>>a[i].d;
	sort(a+1,a+1+m,cmp);

	for(int i = 1;i<=m;i++)
	{
		int L = a[i].l,D = a[i].d;
		int val = *s.lower_bound(L);
		if(cnt[val])
		{
			sum-=D,cnt[val]--;
			if(!cnt[val])s.erase(val);
		}
	}
	cout<<sum<<endl;
	return 0;
}
posted on 2023-07-04 00:21  nannandbk  阅读(104)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3