Educational Codeforces Round 81 (Div. 2)

比赛链接:https://codeforces.com/contest/1295

A - Display The Number

题意

输出按照电子钟表的格式用 n 段能组成的最大值。(1≤n≤105

思路

每两段组成 1 增加位长,如有余与数首的 1 组成 7。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    if (n & 1) cout << '7' << string((n - 3) / 2, '1') << "\n";
    else cout << string(n / 2, '1') << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B - Infinite Prefixes

题意

一个 01 串可以无限串连,问 01 个数之差为 x 的前缀有多少个(考虑空串)。(1≤|s|≤105,10-9≤x≤109

思路

递推一遍记录每个位置 01 个数的差,串尾的差还表示下一串与上一串的每个位置差的变化情况。

无限的情况是串尾之差为 0,且串中有 x。

否则记录所有最终可以变化为 x 的位置个数,判定条件:同正负,与 x 之差可以整除串尾的差。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, x; cin >> n >> x;
    string s; cin >> s;
    int cnt[n] = {};
    for (int i = 0; i < n; i++) {
        if (i != 0) cnt[i] = cnt[i - 1];
        if (s[i] == '0') ++cnt[i];
        else --cnt[i];
    }
    if (cnt[n - 1] == 0) cout << (count(cnt, cnt + n, x) ? -1 : 0) << "\n";
    else {
        set<int> st;
        for (int i : cnt) {
            if (1LL * (x - i) * cnt[n - 1] >= 0 and (x - i) % cnt[n - 1] == 0) {
                st.insert(i);
            }
        }
        map<int, int> Map;
        for (int i : cnt) ++Map[i];
        int ans = 0;
        for (int i : st) {
            ans += Map[i];
        }
        cout << ans + (x == 0) << "\n";
    }
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C - Obtain The String

题意

利用字符串 s 的子序列串连成字符串 t,问最少需要用多少个子序列。(1≤|s|≤105,1≤|t|≤105

思路

贪心,记录字符串 s 中每个字符的位置,遍历字符串 t,每次二分查找大于当前位置的字符位置。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    string s, t; cin >> s >> t;
    vector<int> v[26];
    for (int i = 0; i < s.size(); i++) {
        v[s[i] - 'a'].push_back(i);
    }
    int ans = 1, pos = -1;
    for (int i = 0; i < t.size(); i++) {
        int id = t[i] - 'a';
        if (v[id].size() == 0) {
            cout << "-1" << "\n";
            return;
        } else {
            auto it = upper_bound(v[id].begin(), v[id].end(), pos);
            if (it != v[id].end()) {
                pos = *it;
            } else {
                pos = v[id][0];
                ++ans;
            }
        }
    }
    cout << ans << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

D - Same GCDs

题意

给定 a,m,计算 [0,m) 内满足 gcd(a,m)=gcd(a+x,m) 的 x 个数。(1≤a<m≤1010

思路

设 gcd(a,m)=d,所求即满足 gcd(a/d,m/d)=gcd((a+x)/d,m/d)=1 的 x 的个数,即欧拉函数 phi(m/d) 。

代码

#include <bits/stdc++.h>
using LL = long long;
using namespace std;

LL phi(LL n) {
    LL ret = n;
    for (LL i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            ret = ret / i * (i - 1);
            while (n % i == 0)
                n /= i;
        }
    }
    if (n > 1) ret = ret / n * (n - 1);
    return ret;
}

void solve() {
    LL a, m; cin >> a >> m;
    cout << phi(m / __gcd(a, m)) << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

 

posted @ 2020-04-19 16:39  Kanoon  阅读(115)  评论(0编辑  收藏  举报