Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)题解

总体情况

更极限了,30分钟逆转局面,5分钟成就佳绩!

image
image

对于 lzh999Killer_Sansyxbb

您在 ABC383 中表现优异,获得:

永不言弃

2024年12月7日

A - Humidifier 1

题目描述

AtCoder 公司办公室有一个加湿器。当前时间是 \(0\) ,加湿器内没有水。

你要给加湿器加水 \(N\) 次。第 \(i\) 次加水( \(1 \leq i \leq N\) )发生在时间 \(T_i\) ,您加了 \(V_i\) 升水。保证所有 \(1 \leq i \leq N-1\)\(T_i \le T_{i+1}\)

然而,加湿器漏水了,只要里面有水,单位时间内水量就会减少 \(1\) 升。

求在 \(T_N\) 时加完水后加湿器中剩余的水量。

思路分析

直接模拟即可。

代码

// Problem: A - Humidifier 1
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(int x,char y){write(x);write(y);}
	#ifndef int
	void read(long long &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void write(long long x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(long long x,char y){write(x);write(y);}
	#endif
	signed main(){
		int sum = 0,now = 1;
		int n;cin >> n;
		for(int i = 1;i<=n;i++){
			int t,y;read(t);read(y);
			while(now<t){
				now++;sum--;
			}
			sum = max(sum,0);
			sum += y;
		}
		write(sum);
		return 0;
	}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
//	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

B - Humidifier 2

题目描述

AtCoder 公司办公室可以表示为由 \(H\) 行和 \(W\) 列组成的网格。让 \((i, j)\) 表示从上往下第 \(i\) 行和从左往上第 \(j\) 列的单元格。

每个单元格的状态由一个字符 \(S_{i,j}\) 表示。如果 \(S_{i,j}\)#,则该单元格包含一张桌子;如果 \(S_{i,j}\).,则该单元格是一层楼。可以保证至少有两个楼层单元格。

您将选择两个不同的楼层单元格,并在每个单元格中放置一个加湿器。

放置加湿器后,当且仅当一个单元格 \((i,j)\) 与至少一个加湿器单元格 \((i',j')\) 的曼哈顿距离 \(D\) 在内时,该单元格才被加湿。 \((i,j)\)\((i',j')\) 之间的曼哈顿距离定义为 \(|i - i'| + |j - j'|\) 。需要注意的是,任何放置了加湿器的楼层单元总是加湿的。

求加湿楼层单元的最大可能数目。

思路分析

暴力枚举两个加湿器的位置,直接模拟即可。

时间复杂度:\(O(n^6)\)

代码

// Problem: B - Humidifier 2
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(int x,char y){write(x);write(y);}
	#ifndef int
	void read(long long &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void write(long long x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(long long x,char y){write(x);write(y);}
	#endif
	const int MAXN = 12;
	char a[MAXN][MAXN];int n,m,d;
	signed main(){
		read(n);read(m);read(d);
		for(int i = 1;i<=n;i++){
			scanf("%s",a[i]+1);
		}
		int ans = 0;
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=m;j++){
				for(int x = 1;x<=n;x++){
					for(int y = 1;y<=m;y++){
						if(x==i&&y==j) continue;
						if(a[i][j]=='#') continue;
						if(a[x][y]=='#') continue;
						int cnt =0 ;
						for(int u1 = 1;u1<=n;u1++){
							for(int u2 = 1;u2<=m;u2++){
								if(a[u1][u2]=='#') continue;
								if(abs(u1-i)+abs(u2-j)<=d){
									cnt++;
								}else if(abs(u1-x)+abs(u2-y)<=d){
									cnt++;
								}
							}
						}
						ans = max(ans,cnt);
					}
				}
			}
		}
		write(ans);
		return 0;
	}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
//	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

C - Humidifier 3

题目描述

AtCoder 公司的办公室是由 \(H\) 行和 \(W\) 列组成的网格。让 \((i, j)\) 表示从上往下第 \(i\) 行和从左往上第 \(j\) 列的单元格。

每个单元格的状态由一个字符 \(S_{i,j}\) 表示。如果 \(S_{i,j}\) 为 "#",则该单元格为墙壁;如果 \(S_{i,j}\) 为".",则该单元格为地板;如果 \(S_{i,j}\) 为 "H",则该单元格的地板上放置了加湿器。

如果从至少一个加湿器单元格向上、向下、向左或向右移动最多 \(D\) 次而不经过墙壁,则该单元格被视为加湿单元格。需要注意的是,任何有加湿器的单元格总是加湿的。

求加湿地板单元格的数量。

思路分析

小丑题。

直接将每一个加湿器放进bfs的队列里面。

如果一个点出现过两次,那么前面出现的那一次的次数一定要多于后一次出现的次数,所以相同的不进去,直接 BFS 即可。

代码

// Problem: B - Humidifier 2
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(int x,char y){write(x);write(y);}
	#ifndef int
	void read(long long &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void write(long long x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(long long x,char y){write(x);write(y);}
	#endif
	const int MAXN = 1000+20;
	char a[MAXN][MAXN];int n,m,d;
	int h[MAXN][MAXN],s[MAXN][MAXN];
	int left[MAXN][MAXN],right[MAXN][MAXN],up[MAXN][MAXN],down[MAXN][MAXN];
	int vis[MAXN][MAXN],ans;
	queue<pair<pair<int,int>,int>> q;
	void add(int x,int y,int s){
		if(!(~s)) return;
		if(x<1||x>n) return;
		if(y<1||y>m) return;
		if(a[x][y]=='#') return;
		if(vis[x][y]) return;
		vis[x][y] = 1;ans++;
		// cout << x<< " " << y << endl;
		q.push({{x,y},s});
	}
	signed main(){
		read(n);read(m);read(d);
		for(int i = 1;i<=n;i++){
			scanf("%s",a[i]+1);
		}
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=m;j++){
				if(a[i][j]=='H') add(i,j,d);
			}
		}
		while(!q.empty()){
			auto tmp = q.front();
			q.pop();
			add(tmp.first.first-1,tmp.first.second,tmp.second-1);
			add(tmp.first.first+1,tmp.first.second,tmp.second-1);
			add(tmp.first.first,tmp.first.second-1,tmp.second-1);
			add(tmp.first.first,tmp.first.second+1,tmp.second-1);
		}
		write(ans);
		return 0;
	}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
//	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

D - 9 Divisors

题目描述

求恰好有 \(9\) 个正因数的不大于 \(N\) 的正整数的个数。

思路分析

首先这个题目要读懂(要看原文才知道翻译的时候把正因数翻译成为了正整数

考虑哪些整数有 9 个因数。

如果做过 BS 期中考试卷的话我们知道完全平方数的因数个数有奇数个。

考虑一个完全平方数 \(n=a^2\)。对于所有 \(a\) 的因数 \(i\),都会有 \(\displaystyle\frac{n}{i}\neq i\),且\(\displaystyle\frac{n}{i}\in \N^+\)

所以 \(a\) 的因数个数为 \(5\) 个。

分为两种情况

  1. \(a=pq(p,q\) 是质数且\(p\neq q)\),这个时候因数有 \(1,q,q^2,p,pq,pq^2,p^2,p^2q,p^2q^2\),这种情况直接使用 埃氏筛 来解决。
  2. \(a=p^4,n=p^8\),这个时候因数有 \(p^0,p^1,p^2,p^3,p^4,p^5,p^6,p^7,p^8\),直接暴力枚举即可。

时间复杂度:\(O(\sqrt n\log \log \sqrt n)\)

代码

// Problem: D - 9 Divisors
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(int x,char y){write(x);write(y);}
	#ifndef int
	void read(long long &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void write(long long x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(long long x,char y){write(x);write(y);}
	#endif
	const int MAXN = 4e6+10;
	int ys[MAXN],a[MAXN],b[MAXN],P[MAXN];
	signed main(){
		int n;
		int ans = 0;
		read(n);
		for(int i = 2;i<MAXN;i++){
			if(!ys[i]){
				for(int j = 2*i;j<MAXN;j+=i){
					ys[j]++;
					if(ys[j]==1) a[j] = i;
					else b[j] = i;
				}
			}else if(ys[i]==2){
				if(i!=a[i]*b[i]) continue;
				if(i*i<=n) ans++;
			}
			
		}
		for(int i = 2;i<MAXN;i++){
			if(ys[i]) continue;
			if(i*i>MAXN) break;
			if(i*i*i>MAXN) break;
			if(i*i*i*i>MAXN) break;
			if(i*i*i*i*i*i*i*i<=n) ans++;
		}
		write(ans);
		return 0;
		
	}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
//	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

F - Diversity

题目描述

一家商店里有 \(N\) 种商品出售。其中 \(i\) 件产品的价格为 \(P_i\) 日元,效用值为 \(U_i\) ,颜色为 \(C_i\)

你将从这些 \(N\) 产品中选择一个子集购买(可能一个都不)。所选产品的总价最多为 \(X\) 日元。

您的满意度为 \(S + T \times K\) ,其中 \(S\) 是所选产品的效用总和,而 \(T\) 是所选产品中不同颜色的数量。这里, \(K\) 是一个给定的常数。

您选择的产品将使您的满意度最大化。求最大满意度。

思路分析

这题唯一的瓶颈就是 \(T\) 不好处理。那我们可以将商品按照颜色排序,然后 dp。定义状态为:\(f_{i,j,0/1}\) 代表前 \(i\) 个商品中的总价为 \(j\),其中与 \(i\) 颜色一致的商品现在选/没选的最大满意度。

状态转移方程显然。

代码

// Problem: F - Diversity
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_f
// Memory Limit: 1024 MB
// Time Limit: 2500 ms

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(int x,char y){write(x);write(y);}
	#ifndef int
	void read(long long &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void write(long long x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');}
	}
	void write(long long x,char y){write(x);write(y);}
	#endif
	const int MAXN = 510;
	const int MAXM = 5e4+10;
	const int INF = 0x3f3f3f3f;
	int f[MAXM][2],n,x,k;
	struct node{
		int p,u,c;
	}a[MAXN];
	signed main(){
		read(n);read(x);read(k);
		for(int i = 1;i<=n;i++){
			read(a[i].p);read(a[i].u);read(a[i].c);
		}
		sort(a+1,a+1+n,[](node a,node b){
			return a.c<b.c;
		});
		for(int i = 1;i<=x;i++) f[i][0] = f[i][1] = -INF;
		for(int i = 1;i<=n;i++){
			if(i==1||a[i].c!=a[i-1].c) for(int j = 0;j<=x;j++) f[j][0] = max(f[j][0],f[j][1]);
			for(int j = x;j>=a[i].p;j--){
				if(i==1||a[i].c!=a[i-1].c){
					f[j][1] = max({f[j][1],f[j-a[i].p][0]+k+a[i].u,f[j-a[i].p][1]+k+a[i].u});
				}else{
					f[j][1] = max({f[j][1],f[j-a[i].p][1]+a[i].u,f[j-a[i].p][0]+k+a[i].u});
				}
			}
		}
		int ans = 0;
		for(int i = 0;i<=x;i++) ans = max({ans,f[i][0],f[i][1]});
		write(ans);
		return 0;
	}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
//	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

posted @ 2024-12-07 21:58  辜铜星  阅读(79)  评论(0编辑  收藏  举报