Educational Codeforces Round 81 (Rated for Div. 2)解题报告

Educational Codeforces Round 81 (Rated for Div. 2)

【A.Display The Number】

【题目大意】
问你用n根火柴能表示的最大数字是多少

【解题思路】
容易想到1只需要两根火柴,那么尽量用1,有多的将第一位改为7

【AC代码】

#include <bits/stdc++.h>
#define N 100
#define max(a, b) ((a) > (b) ? (a) :(b))
#define min(a, b) ((a) < (b) ? (a) :(b))
#define _Rep(i, n) for(register int i = 1; i < (n); ++i)
#define Rep(i, n) for(register int i = 1; i <= (n); ++i)
#define _rep(i, n) for(register int i = 0; i < (n); ++i)
#define rep(i, n) for(register int i = 0; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxm = 3e5 + 10;
const ll INF = 0x3f3f3f3f;
inline ll read() {
	register ll x = 0, w = 0; register char ch = 0;
	while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return w ? -x : x;
}
inline void write(register int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
int main() {
	register int t = read();
	while (t--) {
		register int n = read();
		register int cnt = n / 2;
		register int rest = n % 2;
		register string s;
		for (int i = 1; i <= cnt; ++i) {
			s += "1";
		}
		if (rest) s[0] = '7';
		cout << s << endl;
	}
	return 0;
}

【B.Infinite Prefixes】

【题目大意】
t为循环节为s的无限字符串,问t有多少个前缀满足其中0的个数减去1的个数等于x,若有无限个则输出-1,前缀可以为空

【解题思路】
考虑记录s每一位上0与1的差值,如果循环节末尾的差值为0,那么显然答案只有0和-1两种情况,如果末尾不为1,那么随着位数的增长,其差值单调递增或单调减少,而t每增加一个s所增加的差值数是一定的,所以只需要找s中(x - a[i]) % a[n - 1] = 0的个数就可以了

注意要特判x = 0的情况(会被Hack

【AC代码】

#include <bits/stdc++.h>
#define N 100
#define max(a, b) ((a) > (b) ? (a) :(b))
#define min(a, b) ((a) < (b) ? (a) :(b))
#define _Rep(i, n) for(register int i = 1; i < (n); ++i)
#define Rep(i, n) for(register int i = 1; i <= (n); ++i)
#define _rep(i, n) for(register int i = 0; i < (n); ++i)
#define rep(i, n) for(register int i = 0; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxm = 3e5 + 10;
const ll INF = 0x3f3f3f3f;
inline ll read() {
	register ll x = 0, w = 0; register char ch = 0;
	while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return w ? -x : x;
}
inline void write(register int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
int a[maxn];
int main() {
	register int t = read();
	while (t--) {
		memset(a, 0, sizeof(a));
		register int n = read(), x = read();
		register string s;
		cin >> s;
		register int cnt0 = 0, cnt1 = 0;
		register int Max = -0x3f3f3f3f, Min = 0x3f3f3f3f;
		for (int i = 0; i < n; ++i) {
			if (s[i] == '0') ++cnt0;
			else ++cnt1;
			a[i] = cnt0 - cnt1;
			Max = max(Max, a[i]);
			Min = min(Min, a[i]);
		}
		if (!a[n - 1]) {
			if (!x || Min <= x && x <= Max) puts("-1");
			else puts("0");
		}
		else {
			register int ans = x ? 0 : 1;
			for (int i = 0; i < n; ++i) {
				register int t = (x - a[i]) / a[n - 1];
				if ((x == a[i]) || (t > 0 && a[n - 1] * t + a[i] == x)) ++ans;
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}

【C.Obtain The String】

【题目大意】
问你要往空串z中增加几次s的子序列才能得到串t,如果不能得到输出-1

【解题思路】
记录s中每个字母出现过的位置,遍历串t,如果s中没有t[i],那么答案显然为-1,每次我们找到出现在上一次位置后面的t[i],如果找不到就让答案加一,重新查找

【AC代码】

#include <bits/stdc++.h>
#define N 100
#define max(a, b) ((a) > (b) ? (a) :(b))
#define min(a, b) ((a) < (b) ? (a) :(b))
#define _Rep(i, n) for(register int i = 1; i < (n); ++i)
#define Rep(i, n) for(register int i = 1; i <= (n); ++i)
#define _rep(i, n) for(register int i = 0; i < (n); ++i)
#define rep(i, n) for(register int i = 0; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxm = 3e5 + 10;
const ll INF = 0x3f3f3f3f;
inline ll read() {
	register ll x = 0, w = 0; register char ch = 0;
	while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return w ? -x : x;
}
inline void write(register int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
char s[maxm];
char p[maxm];
int main() {
	register int t = read();
	while (t--) {
		register vector<int> v[30];
		scanf(" %s", s);
		scanf(" %s", p);
		register int ls = strlen(s);
		register int lp = strlen(p);
		for (register int i = 0; i < ls; ++i) {
			v[s[i] - 'a'].push_back(i);
		}
		register int ans = 1;
		register int temp = -1;
		register int i = 0, j = 0;
		while(i < lp) {
			register int ch = p[i] - 'a';
			if (v[ch].size() == 0) {
				puts("-1");
				break;
			}
			register int l = v[ch].size();
			register int j = upper_bound(v[ch].begin(), v[ch].end(), temp) - v[ch].begin();
			if (j < l) temp = v[ch][j], ++i;
			else ++ans, temp = -1;
		}
		if (i < lp) continue;
		else write(ans), puts("");
	}
	return 0;
}

【D.Same GCDs】

【题目大意】
问你在[0, m)中有多少个x满足gcd(a, m) = gcd(a + x, m),m大于a

【解题思路】
设a = k1 * n, m = k2 * n,且gcd(k1, k2) = 1
则gcd(a, m) = n
a + x = k1 * n + x = (k1 + x / n) * n
gcd(a + x, m) = gcd( (k1 + x / n) * n, k2 * n)
要使gcd(a + x, m) = gcd(a, m)
则gcd(k1 + x / n, k2) = 1
又x属于[0, m),那么答案即为[k1, k1 + k2)中与k2互质的正整数个数(m / n = k2)
又因为k1与k2互质且k2 > k1(m > a),故答案等价于[0, k2)中与k2互质的个数,即欧拉函数k2 = m / n = m / gcd(a, m)的值

【AC代码】

#include <bits/stdc++.h>
#define N 100
#define max(a, b) ((a) > (b) ? (a) :(b))
#define min(a, b) ((a) < (b) ? (a) :(b))
#define _Rep(i, n) for(register int i = 1; i < (n); ++i)
#define Rep(i, n) for(register int i = 1; i <= (n); ++i)
#define _rep(i, n) for(register int i = 0; i < (n); ++i)
#define rep(i, n) for(register int i = 0; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxm = 3e5 + 10;
const ll INF = 0x3f3f3f3f;
inline ll read() {
	register ll x = 0, w = 0; register char ch = 0;
	while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return w ? -x : x;
}
inline void write(register int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
inline ll get_euler(ll n) {
	register ll res = n;
	for (register ll i = 2; i * i <= n; ++i) {
		if (n % i == 0) {
			res = res / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	}
	if (n > 1) res = res / n * (n - 1);
	return res;
}
inline ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main() {
	register int t = read();
	while (t--) {
		register ll a = read(), m = read();
		printf("%lld\n", get_euler(m / gcd(m, a)));
	}
	return 0;
}
发布了40 篇原创文章 · 获赞 2 · 访问量 3224

猜你喜欢

转载自blog.csdn.net/weixin_44211980/article/details/104111834