AtCoder Beginner Contest 291 A-F 题解

。。。

比赛链接

A - camel Case

直接循环判断。

#include<cstdio>
#include<cstring>
const int N = 20;
char s[N];
int main() {
	scanf("%s", s + 1);
	for(int i = 1; i <= strlen(s + 1); i ++) {
		if(s[i] >= 'A' && s[i] <= 'Z') {
			printf("%d", i);
			return 0;
		}
	}
	
	return 0;
}

B - Trimmed Mean

排个序,中间 3n 个数求和,然后求平均数。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 505;
int n, a[N], ans;
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= 5 * n; i ++) {
		scanf("%d", &a[i]);
	}
	
	sort(a + 1, a + 1 + 5 * n);
	
	for(int i = n + 1; i <= 4 * n; i ++) {
		ans += a[i];
	}
	
	printf("%.5f", 1.0 * ans / 3 / n);

	return 0;
}

C - LRUD Instructions 2

重复走点的条件就是,当前点的左右操作之差,上下操作之差,与之前点的差值分别相等。

感性理解一下。

#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
#define mk make_pair
#define PII pair<int, int>
const int N = 2e5 + 5;

int n, cl, cr, cd, cu;
char s[N];
set< PII >  mp;
int main() {
	scanf("%d %s", &n, s + 1);
	int x = 0, y = 0;
	mp.insert(mk(0, 0));
	for(int i = 1; i <= n; i ++) {
		if(s[i] == 'L') cl ++;
		else if(s[i] == 'U') cu ++;
		else if(s[i] == 'R') cr ++;
		else cd ++;
		PII now = mk(cl - cr, cu - cd);
		if(mp.count(now)) {
			puts("Yes");
			return 0;
		}
		mp.insert(now);
	}
	puts("No");
	return 0;
}

D - Flip Cards

定义 dp[i][0/1] 为已经操作完前 i 位,第 i 位翻/不翻 的满足条件的方案总数。

然后枚举判断前后牌的数值是否满足条件。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
const int N = 2e5 + 5;
const ll mod = 998244353;
int n, a[N], b[N];
ll dp[N][2];

int main() {
	scanf("%d", &n);
	
	for(int i = 1; i <= n; i ++) {
		scanf("%d %d", &a[i], &b[i]);
	}
	dp[1][0] = dp[1][1] = 1;
	
	for(int i = 2; i <= n; i ++) {
		if(a[i] != a[i - 1]) dp[i][0] = (dp[i][0] + dp[i - 1][0]) % mod;
		if(a[i] != b[i - 1]) dp[i][0] = (dp[i][0] + dp[i - 1][1]) % mod;
		if(b[i] != a[i - 1]) dp[i][1] = (dp[i][1] + dp[i - 1][0]) % mod;
		if(b[i] != b[i - 1]) dp[i][1] = (dp[i][1] + dp[i - 1][1]) % mod;
	}
	
	printf("%lld", (dp[n][0] + dp[n][1]) % mod);
	return 0;
}

E - Find Permutation

结论:对于任何拓扑顺序 P,序列 \(A\) 使 \(A_{P_i}=i\) 满足拓扑顺序定义的条件。反之亦然。因此,当且仅当 \(G\) 的拓扑顺序是唯一的时候,\(A\) 是唯一的。而 \(G\) 的拓扑顺序唯一,当且仅当在实际的拓扑排序过程中,下一个要选择的顶点(入度为 \(0\) )总是唯一的,这可以很容易地检查出来

(鬼知道为什么我写 T 了)

(官方代码)
#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,m;
	cin >> n >> m;
	
	vector<vector<int>>G(n);
	vector<int>deg(n);
	for(int i=0;i<m;i++){
		int x,y;
		cin >> x >> y;
		x--,y--;
		G[x].push_back(y);
		deg[y]++;
	}
	
	vector<int>ans(n);
	queue<int>q;
	int cnt=0;
	for(int i=0;i<n;i++)if(deg[i]==0)q.push(i);
	while(!q.empty()){
		if(q.size()!=1){
			cout << "No" << endl;
			return 0;
		}
		int v=q.front();q.pop();
		ans[v]=++cnt;
		for(auto vv:G[v])if(!--deg[vv])q.push(vv);
	}

	cout << "Yes" << endl;
	for(int i=0;i<n;i++)cout << ans[i] << " \n"[i==n-1];
}

F - Teleporter and Closed off

。。。。

(官方题解)
#include <bits/stdc++.h>
using namespace std;
#define INF (int)1e+9

int main(void) {
	int n,m,ans;
	cin>>n>>m;
	vector<string> s(n);
	for(int i=0;i<n;i++)cin>>s[i];

	vector<int> dp0(n,INF),dp1(n,INF);
	dp0[0]=0;
	for(int i=1;i<n;i++){
		for(int j=1;j<=min(m,i);j++){
			if(s[i-j][j-1]=='1')dp0[i]=min(dp0[i],dp0[i-j]+1);
		}
	}
	dp1[n-1]=0;
	for(int i=n-2;i>=0;i--){
		for(int j=1;j<=min(m,n-1-i);j++){
			if(s[i][j-1]=='1')dp1[i]=min(dp1[i],dp1[i+j]+1);
		}
	}
  
	for(int k=1;k<n-1;k++){
                ans=INF;
		for(int i=max(k-m+1,0);i<k;i++){
			for(int j=k+1;j<min(n,k+m);j++){
				if(s[i][j-i-1]=='1')ans=min(ans,dp0[i]+dp1[j]+1);
			}
		}
                if(ans==INF)cout<<-1;
		else cout<<ans;
		if(k<(n-2))cout<<" ";
		else cout<<endl;
	}	
	return 0;
}

posted @ 2023-02-27 20:12  Spring-Araki  阅读(39)  评论(0编辑  收藏  举报