Codeforces Round #443 (Div. 2)

A

比较傻用了二分

#include<bits/stdc++.h>

using namespace std;
#define LL long long
#define mst(a, b)	memset(a, b, sizeof a)
#define pb push_back
const int qq = 1e7 + 10;
const int MOD = 1e9 + 7;
const int INF = 1e9 + 10;
int vis[qq];
int a[qq], b[qq];

int main() {
	int n;	scanf("%d", &n);
	mst(vis, 0);
	int start = -1;
	for(int i = 1; i <= n; ++i) {
		scanf("%d%d", a + i, b + i);
		if(start == -1) {
			start = a[i];
		} else {
			int l = 0, r = 1e6;
			int tmp;
			while(l <= r) {
				int mid = (l + r) >> 1;
				if(a[i] + mid * b[i] > start) {
					tmp = mid;
					r = mid - 1;
				} else {
					l = mid + 1;
				}
			}
			start = a[i] + tmp * b[i];
		}
	}
	printf("%d\n", start);
	return 0;
}


B

很显然当k>=n的时候肯定就是数列中数最大的那个数的人赢,其他情况模拟下即可

#include<bits/stdc++.h>

using namespace std;
#define LL long long
#define mst(a, b)	memset(a, b, sizeof a)
#define pb push_back
const int qq = 1e5 + 10;
const int MOD = 1e9 + 7;
const int INF = 1e9 + 10;

int vis[505];
int a[505];
struct Node {
	int id, pw;
}p;

int main() {
	int n, k;	scanf("%d%d", &n, &k);
	int maxn = -1, id = -1;
	for(int i = 1; i <= n; ++i) {
		scanf("%d", a + i);
		if(a[i] > maxn) {
			maxn = a[i];
			id = i;
		}
	}
	if(k > n) {
		printf("%d\n", maxn);
		return 0;
	}
	queue<Node> Q;
	if(a[2] > a[1]) {
		id = 2, maxn = a[2];
	} else {
		id = 1, maxn = a[1];
	}
	for(int i = 1; i <= n; ++i) {
		p.id = i, p.pw = a[i];
		if(id == i)	continue;
		Q.push(p);
	}
	while(true) {
		p = Q.front();
		Q.pop();
		if(maxn > p.pw) {
			vis[id]++;
			Q.push(p);
		} else {
			Node tmp;
			tmp.pw = maxn, tmp.id = id;
			Q.push(tmp);
			maxn = p.pw;
			id = p.id;
			vis[id]++;
		}
		if(vis[id] == k) {
			printf("%d\n", maxn);
			return 0;
		}
	}
}

C

我们知道如果进行 | 操作那么就可以确定某些位置肯定是1,如果进行 & 操作就可以确定某些位置肯定是0, 如果进行 ^ 操作如果是1的位置肯定是0,是0的位置肯定是1,未操作的位置可以覆盖 ^ 操作标记,如果本身已经被 ^ 操作覆盖那么这位重新变成未操作状态

#include<bits/stdc++.h>

using namespace std;
#define LL long long
#define mst(a, b)	memset(a, b, sizeof a)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
const int qq = 1e5 + 10;
const int MOD = 1e9 + 7;
const int INF = 1e9 + 10;
int bit[15];

int main() {
	mst(bit, -1);
	int n;	scanf("%d", &n);
	char op[6];
	int x;
	while(n--) {
		scanf("%s%d", op, &x);
		int cnt = 0;
		if(op[0] == '|') {
			while(x > 0) {
				if(x & 1)	bit[cnt] = 1;
				cnt++;
				x >>= 1;
			}
		} else if(op[0] == '&') {
			x = 1023 - x;
			while(x > 0) {
				if(x & 1)	bit[cnt] = 0;
				cnt++;
				x >>= 1;
			}
		} else {
			while(x > 0) {
				if(x & 1) {
					if(bit[cnt] == 1)	bit[cnt] = 0;
					else if(bit[cnt] == 0)	bit[cnt] = 1;
					else if(bit[cnt] == -1)	bit[cnt] = 2;
					else if(bit[cnt] == 2)	bit[cnt] = -1;
				}
				cnt++;
				x >>= 1;
			}
		}
	}
	int ans[3];
	ans[0] = 0, ans[1] = 1023, ans[2] = 0;
	for(int i = 0; i < 10; ++i) {
		if(bit[i] == 1)	ans[0] += (1 << i);
		else if(bit[i] == 0)	ans[1] -= (1 << i);
		else if(bit[i] == 2)	ans[2] += (1 << i);
	}
	printf("3\n| %d\n& %d\n^ %d\n", ans[0], ans[1], ans[2]);
	return 0;
}


D

题意:n个数字,讲这n个数字再重复m - 1次,删掉连续的k个相同的数,直到删除到不能再删为止,问最后剩下多少个数

思路:我们可以考虑相邻两个n个数字之间的删除情况,这两个确定了就可以确定之后的删除情况了,我们首先要预处理一下原本的n个数,也就是能删的就先删掉,具体看代码吧 能力有限

#include<bits/stdc++.h>

using namespace std;
#define LL long long
#define mst(a, b)	memset(a, b, sizeof a)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<LL, LL>
const int qq = 1e5 + 10;
const int MOD = 1e9 + 7;
const int INF = 1e9 + 10;
LL n, k, m;
pill p[qq];

int main() {
	scanf("%lld%lld%lld", &n, &k, &m);
	int pre = -1;
	int top = 0, cnt = 0;
	p[0].fi = -1;
	for(int x, i = 0; i < n; ++i) {
		scanf("%d", &x);
		if(!top || p[top].fi != x) {
			p[++top].fi = x;
			p[top].se = 1;
		} else {
			p[top].se++;
		}
		if(p[top].se == k) {
			p[top--].se -= k;
		}
	}
	LL sum = 0;
	for(int i = 1; i <= top; ++i) {
		sum += p[i].se;
	}
	if(top == 0) {
		printf("0\n");
		return 0;
	}
	if(m == 1) {
		printf("%d\n", sum);
	} else if(k >= n) {
		if(top == 1) {
			printf("%lld\n", sum * m % k);
		} else {
			printf("%lld\n", sum * m);
		}
	} else if(k < n) {
		if(top == 1) {
			printf("%lld\n", sum * m % k);
		} else {
			int l = 1, r = top;
			LL d = 0, tmp = 0;
			while(l < r) {
				if(p[l].fi != p[r].fi)	break;
				if((p[l].se + p[r].se) % k == 0) {
					d += p[l].se + p[r].se;
					l++, r--;
				} else {
					d += (p[l].se + p[r].se) - (p[l].se + p[r].se) % k;
					break;
				}
			}
			LL ans = 0;
			if(l < r) {
				printf("%lld\n", sum * m - d * (m - 1));
			} else if(l == r) {
				if(p[l].se * m % k == 0) {
					ans = 0;
				} else {
					ans = sum * m - d * (m - 1) - (p[l].se * m / k * k);
				}
				printf("%lld\n", ans);
			}
		}	
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值