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;
}