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

辜铜星發表於2024-12-07

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^+\)

程式碼


相關文章