比赛链接:

https://ac.nowcoder.com/acm/contest/11185

A.Duplicate Strings

思路:

统计的是字母的数量,先存下字符串每个字母的数量,操作 1 就是将现有字母的数量乘上 \(k + 1\),操作 2 输出 \(c\) 的数量。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 30, mod = 1e9 + 7;
#define LL long long
string s;
LL n, q, cnt[N], k, op;
char c;
int main(){
	cin >> n >> q >> s;
	for (int i = 0; i < s.size(); i++)
		cnt[s[i] - 'a']++;
	while (q--){
		scanf("%lld", &op);
		if (op == 1){
			scanf("%lld", &k);
			for (int i = 0; i < 26; i++)
				cnt[i] = (cnt[i] * (k + 1)) % mod;
		}
		else{
			cin >> c;
			cout << cnt[c - 'a'] << "\n";
		}
	}
	return 0;
}

B.Non-interger Area

思路:

设三个点分别为 \(A(x1, y1),B(x2, y2),C(x3, y3)\),向量的面积就是 \(\frac{1}{2}*\overrightarrow{AB}*\overrightarrow{AC}\)\(\overrightarrow{AB}*\overrightarrow{AC}\) = \(\lvert (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1) \rvert\)
我们可以发现,面积是否为整数,与每个点坐标的奇偶性有关系。而每个点坐标的奇偶组合有四种情况(奇奇,奇偶,偶奇,偶偶),所以我们就可以记录每种组合的情况,然后暴力跑三个点所有的情况,计算答案,但是这个答案有重复,所以要除 6。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL n, x, y, cnt[2][2], ans;
int main(){
	cin >> n;
	for (int i = 1; i <= n; i++){
		scanf("%lld%lld", &x, &y);
		cnt[x & 1][y & 1]++;
	}
	for (int x1 = 0; x1 < 2; x1++)
		for (int y1 = 0; y1 < 2; y1++)
			for (int x2 = 0; x2 < 2; x2++)
				for (int y2 = 0; y2 < 2; y2++)
					for (int x3 = 0; x3 < 2; x3++)
						for (int y3 = 0; y3 < 2; y3++){
							LL s = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1);
							if (s & 1) ans += cnt[x1][y1] * cnt[x2][y2] * cnt[x3][y3];
						}
	cout << ans / 6 << "\n";
	return 0;
}

C.Division

思路:

首先先将输入的序列值转化为变成 1 的操作次数,问题就变成了对一段 >= k 的区间进行操作,使最后的序列中每一个值都变为 0。
因为是减的操作,我们可以想到差分,即操作区间 [l, r] 时,我们让 a[l]++, a[r + 1]--,这样子可以大大地提高效率,问题也就变为了找左右边界匹配了。
接下来遍历序列,当 a[i - k] 的值大于 0 的时候,说明该位置需要 -1 操作,即区间的左边界,我们可以把它先记录下来,当 a[i] < 0 时,说明该位置需要 +1,即区间的右边界。每当找到右边界的时候我们就记录下这个操作的区间,最后输出即可。最后要判断一下有没有左区间没有相对应的右区间,有的话说明无解。

代码:

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define LL long long
#define pb push_back
#define PII pair <int, int>
#define se second
const int N = 2e4 + 10;
LL T, n, k, a[N], x;
void clear(){
	for (int i = 1; i <= n + k; i++)
		a[i] = 0;
}
void solve(){
	cin >> n >> k;
	vector <PII> ans;
	stack <int> l;
	clear();
	for (int i = 1; i <= n; i++){
		cin >> x;
		while(x > 1){
			a[i]++;
			x >>= 1;
		}
	}
	for (int i = n + 1; i >= 1; i--)
		a[i] = a[i] - a[i - 1];
	for (int i = k + 1; i <= n + k; i++){
		if (a[i - k] > 0){
			while (a[i - k]){
				l.push(i - k);
				a[i - k]--;
			}
		}
		if (a[i] < 0){
			while (a[i]){
				if (l.empty()){
					cout << "-1\n";
					return;
				}
				ans.pb({l.top(), i - 1});
				l.pop();
				a[i]++;
			}
		}
	}
	if (s.size()){
		cout << "-1\n";
		return;
	}
	cout << ans.size() << "\n";
	for (auto x : ans)
		cout << x.fi << " " << x.se << "\n";
}
int main(){
	cin >> T;
	while (T--)
		solve();
	return 0;
}
posted on 2022-02-25 19:24  Hamine  阅读(56)  评论(0编辑  收藏  举报