Codeforces Round #483 (Div. 2) /Codeforces 984 ABCD

比赛链接

摸鱼场

A. Game

题目大意:有两位玩家,和一串数字,两位玩家轮流拿走一些数字,玩家1想要把最小的数留下来,玩家2想把最大的数字留下来。问经过操作后最后留下的数字是什么。

分析:就是中间大的那个,不过这里要分n的奇偶情况

奇数时直接是n/2(向下取整),偶数时是(n/2-1)

不懂的可以自己模拟一下。

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip> 
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
int a[1111];
int main() {
	int n;
	while (~scanf("%d", &n)) {
		for (int i = 0; i < n; i++) {
			scanf("%d", &a[i]);
		}
		sort(a, a + n);
		if (n & 1) printf("%d\n", a[n / 2]);
		else printf("%d\n", a[n / 2 - 1]);
	}
	return 0;
}

B. Minesweeper

题目大意:给出一个字符串阵,问它是否符合扫雷标准格式。

扫雷标准为:*代表雷,数字代表这个格子的八联通块的雷的数目,如果为0的时候用 . 代替。

分析:暴力解。

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip> 
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
char str[111][111];
int main() {
	int n, m;
	while (~scanf("%d%d", &n, &m)) {
		memset(str, 0, sizeof(str));
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				cin >> str[i][j];
			}
		}
		bool flag = false;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				int cnt = 0;
				if (str[i][j] == '*') continue;

				if (str[i - 1][j - 1] == '*') cnt++;
				if (str[i - 1][j] == '*') cnt++;
				if (str[i - 1][j + 1] == '*') cnt++;
				if (str[i][j - 1] == '*') cnt++;
				if (str[i][j + 1] == '*') cnt++;
				if (str[i + 1][j - 1] == '*') cnt++;
				if (str[i + 1][j] == '*') cnt++;
				if (str[i + 1][j + 1] == '*') cnt++;
				if (cnt == 0 && str[i][j] == '.') continue;
				if (cnt == str[i][j] - '0') continue;
				else {
					flag = true;
					break;
				}
			}
		}
		if (flag)printf("NO\n");
		else printf("YES\n");
	}
	return 0;
}

C. Finite or not?

题目大意:给出p,q,b,问p/q在b进制下是否能有限表示(就是有限小数)

分析:如果p/q在b进制下是有限的,那么(p*b^k)%q=0。

显然我们能枚举k,因为数据都是longlong的,所以要一些技巧。

那么我们首先对p/q约分,然后不断对b,q约分直到q==1或者大约64次后q!=1。

前者表示能有限表示,后者反之。

之所以是64次是因为考虑到极限数据p=1,q=1e18,b=2,这种情况下要64次(但是推荐70次左右)

这里还需要一个剪枝,如果某一段算的gcd(b,q)=1表示不能再约了,显然不用再算下去。(没有这个剪枝要t的)

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip> 
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
LL gcd(LL a, LL b) {
	return b == 0 ? a : gcd(b, a%b);
}
int main() {
	int n;
	LL p, q, b;
	while (~scanf("%d", &n)) {
		while (n--) {
			scanf("%I64d%I64d%I64d", &p, &q, &b);
			LL d = gcd(p, q);
			p /= d, q /= d;
			bool flag = false;
			for (int i = 0; i < 74; i++) {
				if (q == 1) {
					flag = true;
					break;
				}
				d = gcd(q, b);
				if (d == 1) {
					flag = false;
					break;
				}
				else {
					while (q%d == 0)
						q /= d;
				}
			}
			printf("%s\n", flag ? "Finite" : "Infinite");
		}
	}
	return 0;
}

D. XOR-pyramid

题目大意:给出一个公式,然后一串数字,

询问q次,问在区间[l,r]中的子串中,代入公式的最大值是多少。

分析:看公式就知道其实是一个数塔形式的计算


那么显然我们能n^2算出所有区间的值。

然后看到数塔求最值的话显然可以用dp的思想(不过注意一下下表的表示)

那么也就是说我们先n^2算出所有区间的值,然后n^2动态规划出所有区间的最大值。

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip> 
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
LL sum[5555][5555];
LL ans[5555][5555];
int main() {
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%I64d", &sum[1][i]);
	int cnt = n - 1;
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j <= cnt; j++) {
			sum[i][j] = sum[i - 1][j] ^ sum[i - 1][j + 1];
		}
		cnt--;
	}
	for (int i = 1; i <= n; i++)
		ans[i][i] = sum[1][i];
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j + i - 1 <= n; j++) {
			int x = j + i - 1;
			ans[j][x] = max(sum[i][j], max(ans[j][x - 1], ans[j + 1][x]));
		}
	}
	int q;
	scanf("%d", &q);
	while (q--) {
		int l, r;
		scanf("%d%d", &l, &r);
		printf("%I64d\n", ans[l][r]);
	}
	return 0;
}
没有E哦

猜你喜欢

转载自blog.csdn.net/xiuya19/article/details/80335618