Atcoder

Beginner Contest 276

No. Task Name Solution
A Rightmost 模拟
B Adjacency List 模拟
C Previous Permutation 模拟+思维
D Divide by 2 or 3 模拟+数学
E Round Trip bfs+优化
F (待完成) Double Chance 数学
G (待完成) Count Sequences 数学



A – Rightmost


题目大意

给你一个字符串,让你找到在最右边的

a

,如果没有就输出

-1


解法分析

模拟。

先设答案为

-1


然后去找最右边的

a


AC Code#1

# include <bits/stdc++.h>
# define RI register int
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
using namespace std;

char s[205]; 

int main(){
	scanf("%s", s+1);
	int n = strlen(s+1), ans = -1;
	rep(i, n) if (s[i] == 'a') ans = i;
	cout << ans;
	return 0;
}



B – Adjacency List


题目大意

给你一张无向图,让你升序输出每个节点所连的点。


解法分析


AC Code#1

# include <bits/stdc++.h>
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define pb push_back
# define RI register int
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
using namespace std;

int n, m;

vector <int> g[200005];

int main(){
	scanf("%d%d", &n, &m);
	for (int i = 1;i <= m;i++){
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v);
		g[v].pb(u);
	}
	for (int i = 1;i <= n;i++){
		printf("%d ", g[i].size());
		sort (g[i].begin(), g[i].end());
		for (int j = 0;j < g[i].size();j++) printf("%d ", g[i][j]); puts("");
	}
	return 0;
}




C – Previous Permutation


题目大意

有一个 1 到 n 的排序 ,问它的上一个全排列是什么


解法分析

这题很像

这题

,观察数据可以发现直接枚举是不行的,经过思考可以发现只要把后面的顺序改一下就可以了,具体看代码。


AC Code#1

# include <bits/stdc++.h>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
using namespace std;

int n, arr[105];

bool cmp(int a, int b){
	return a > b;
}

int main(){
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) scanf("%d", &arr[i]);
	arr[n+1] = inf;
	int ind = 0;
	for (int i = n;i >= 1;i--) if (arr[i] < arr[i-1]){
		ind = i-1; break;
	}
	int nxt = ind, num = -1;
	for (int i = ind;i <= n;i++){
		if (arr[i] < arr[ind] && arr[i] > num)  num = arr[i], nxt = i; 
	}
	swap(arr[ind], arr[nxt]);
	sort (arr+ind+1, arr+n+1, cmp);
	rep(i, n) printf("%d ", arr[i]);
	return 0;
}




D – Divide by 2 or 3


题目大意

有一个长度为

n

的数组,对于每个数



a

i

a_i







a










i





















,你可以把它变成



a

i

2

\frac{a_i}{2}


















2

















a










i












































a

i

3

\frac{a_i}{3}


















3

















a










i








































,问最后可以把 a 所有的数变成同一个数吗,如果可以就输出最小操作次数。


解法分析

可以先把每个数变成与

2



3

互质的数,判断是否相同。

然后找最大公约数。


AC Code#1

# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
//# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};

int n, arr[1005], f[1005][5], ans = 0;

// f_{i,2} : 第 i 个数字有多少个 2
// f_{i,3} : 同上

int main(){
	scanf("%d", &n);
	rep(i, n){
		scanf("%d", &arr[i]);
		while (arr[i] % 2 == 0) arr[i] /= 2, f[i][2]++, ans++;
		while (arr[i] % 3 == 0) arr[i] /= 3, f[i][3]++, ans++;
	}
	rep(i, n) if (arr[i] != arr[1]){
		puts("-1");
		return 0;
	}
	int num1 = f[1][2], num2 = f[1][3];
	rep(i, n) num1 = min(num1, f[i][2]), num2 = min(num2, f[i][3]);
	printf("%d", ans-num1*n-num2*n);
	// 每一个数都要减一遍
	return 0;
}

/*
5
3 6 9 6 6
*/



E – Round Trip


题目大意

有一个



n

×

m

n \times m






n




×








m





的矩阵,其中有


  • .

    :代表空地

  • #

    :代表障碍物

  • S

    :代表起点

问能不能从起点经过空地走回到起点,其中每个起点只能走一遍。


解法分析

观察数据发现矩阵大小只有



1

0

6

10^6






1



0










6












,考虑

bfs

,但是可能会出现



1

×

1

0

6

1 \times 10^6






1




×








1



0










6












的神奇数据,所以对于每一个点



i

,

j

i,j






i


,




j





,可以把它存到



(

i

1

)

×

m

+

j

(i-1) \times m + j






(


i













1


)




×








m




+








j





的位置,接着就是

bfs

模板。


AC Code#1

# pragma GCC optimize(2)
# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
//# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};

char s[1000005], col[1000005], cnt = 0, vis[1000005];

int n, m;

int main(){
	scanf("%d%d", &n, &m);
	int sx, sy;
	for (int i = 1;i <= n;i++){
		getchar(); 
		for (int j = 1;j <= m;j++){
			scanf("%c", &s[(i-1)*m+j]);
			if (s[(i-1)*m+j] == 'S') sx = i, sy = j;
		}
	}
	queue <pii> q;
	q.push({sx, sy});
	col[(sx-1)*m+sy] = 0;
	while (q.size()){
		int x = q.front().fi, y = q.front().se; q.pop();
		int nownum = (x-1)*m+y;
		if (vis[nownum]) continue;
		vis[nownum] = 1;
		for (int i = 0;i < 4;i++){
			int nx = x + dx[i];
			int ny = y + dy[i];
			int nxtnum = (nx-1)*m+ny;
			if (nx < 1 || nx > n || ny < 1 || ny > m || s[nxtnum] == '#' || vis[nxtnum]) continue;
			if (col[nxtnum] && col[nxtnum] != col[nownum]){
				puts("Yes");
				return 0;
			}
			col[nxtnum] = col[nownum];
			if (col[nownum] == 0){
				col[nxtnum] = ++cnt;
			}
			q.push({nx, ny});
		}
	}
	puts("No");
	return 0;
}

/*
5
3 6 9 6 6
*/



F – Double Chance


题目大意


解法分析


AC Code #1




G –


题目大意


解法分析


AC Code #1





Ex –


题目大意


解法分析


AC Code #1




版权声明:本文为yh2021tanghao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/yh2021tanghao/article/details/127710146