Codeforces Round #750 (Div. 2) ABCDEF1

比赛链接:https://codeforces.ml/contest/1582

A. Luntik and Concerts

直接找规律,发现答案肯定只有01。

  1. 模上1,2,3的公倍数,然后暴力枚举
  2. (a+c)%2
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 3e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)
#define endl '\n'

void solve() {
    int T; cin >> T; while (T--) {
        int a, b, c; cin >> a >> b >> c;
        cout << (a+c)%2 << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

B. Luntik and Subsequences

记0的个数为num0,1的个数为num1

f = n u m 1 ∗ 2 n u m 0 f=num1*2^{num0} f=num12num0

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)

void solve() {
    int T; cin >> T; while (T--) {
        int n; cin >> n;
        vector<int> a(n+1);
        ll base = 1, ans = 0;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            if (a[i] == 0) base = base * 2;
        }
        for (int i = 1; i <= n; i++) {
            if (a[i] == 1) ans += base;
        }
        cout << ans << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

C. Grandma Capa Knits a Scarf

从两端开始枚举,直到第一个不同位置,那么答案一定就是两者之一了,暴力判断一下

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)

void solve() {
    int T; cin >> T; while (T--) {
        int n; cin >> n;
        string s; cin >> s;
        char c1, c2;
        int flag = 0;
        for (int i = 0; i < s.size() / 2; i++) {
            if (s[i] != s[n-i-1]) {
                flag = 1;
                c1 = s[i];
                c2 = s[n-i-1];
                break;
            }
        }
        if (!flag) cout << 0 << endl;
        else {
            int l = 0, r = n - 1;
            int num1 = 0;
            int flag1 = 0;
            while (l < r) {
                if (s[l] == s[r]) {
                    l++, r--;
                } else {
                    if (s[l] == c1) {
                        l++;
                        num1++;
                    } else if (s[r] == c1) {
                        r--;
                        num1++;
                    } else {
                        flag1 = 1;
                        break;
                    }
                }
            }
            l = 0, r = n - 1;
            int num2 = 0;
            int flag2 = 0;
            while (l < r) {
                if (s[l] == s[r]) {
                    l++, r--;
                } else {
                    if (s[l] == c2) {
                        l++;
                        num2++;
                    } else if (s[r] == c2) {
                        r--;
                        num2++;
                    } else {
                        flag2 = 1;
                        break;
                    }
                }
            }
            if (flag1 && flag2) cout << -1 << endl;
            else {
                if (flag1 && !flag2) cout << num2 << endl;
                else if (!flag1 && flag2) cout << num1 << endl;
                else cout << min(num1, num2) << endl;
            }
        }
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

D. Vupsen, Pupsen and 0

思路其实很好想,如果是偶数,直接两两配对。如果是奇数,那么我们选择三个数配对,三个数怎么选呢,如果三个数分别为a,b,c,那么我们给a,b一个系数c,c的系数为-(a+b)。这里还有一个坑,即a+b为0。我先是随机找两个数判,然后t了,后来改成两个同符号的就可以了。

记得两两配对需要除上gcd,不然第二种情况 ∑ b i \sum bi bi可能会大于1e9

以下是证明可行性:
奇数时的 ∑ b i \sum bi bi最大可构造的数为1e4,1e4-1,1e4,1e4-1…,因此sum<1e9-1e5,那么剩下的a,b,c系数和肯定小于1e5,因此符合要求

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)
int a[N];
void solve() {
    int T; cin >> T; while (T--) {
        int n; cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        if (n % 2 == 0) {
            for (int i = 1; i <= n; i += 2) {
                cout << -a[i+1] << ' ' << a[i] << ' ';
            }
            cout << endl;
        } else {
            int x, y;
            vector<int> fu, zhen;
            for (int i = 1; i <= n; i++) {
                if (a[i] > 0) zhen.push_back(i);
                else fu.push_back(i);
            }
            if (fu.size() > 1) x = fu[0], y = fu[1];
            else x = zhen[0], y = zhen[1];
            vector<int> vis(n+1), ans(n+1);
            vis[x] = vis[y] = 1;
            int pre = 0;
            for (int i = 1; i <= n; i ++) {
                if (vis[i]) continue;
                if (pre) {
                    int gcd = __gcd(abs(a[i]), abs(a[pre]));
                    ans[i] = -a[pre]/gcd;
                    ans[pre] = a[i]/gcd;
                    vis[pre] = vis[i] = 1;
                    pre = 0;
                } else {
                    pre = i;
                }
            }
            for (int i = 1; i <= n; i++) {
                if (!vis[i]) {
                    ans[x] = ans[y] = a[i];
                    ans[i] = -(a[x]+a[y]);
                    break;
                }
            }
            for (int i = 1; i <= n; i++) cout << ans[i] << ' ';
            cout << endl;
        }
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

E. Pchelyonok and Segments

考虑dp,因为 ( k + 1 ) ∗ k 2 < n \frac{(k+1)*k}{2}<n 2(k+1)k<n k < ( 2 n ) k<\sqrt{(2n)} k<(2n)

因此状态可以表示成 d p [ i ] [ j ] dp[i][j] dp[i][j]代表前i个数当前长度为j的最大值

d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , s u m [ i + j − 1 ] − s u m [ i − 1 ] ) dp[i][j]=max(dp[i][j],sum[i+j-1]-sum[i-1]) dp[i][j]=max(dp[i][j],sum[i+j1]sum[i1])

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)
int a[N];
ll dp[N][500], sum[N];
void solve() {
    int T; cin >> T; while (T--) {
        int n; cin >> n;
        for (int i = 0; i <= n+1; i++) {
            for (int j = 0; j <= sqrt(2*n); j++) {
                dp[i][j] = 0;
            }
        }
        for (int i = 1; i <= n; i++) cin >> a[i], sum[i] = sum[i-1] + a[i];
        dp[n+1][0] = inf;
        for (int i = n; i >= 1; i--) {
            for (int j = 0; j <= sqrt(2*n); j++) {
                dp[i][j] = dp[i+1][j];
                if (j && i + j - 1 <= n && sum[i+j-1] - sum[i-1] < dp[i+j][j-1]) {
                    dp[i][j] = max(dp[i][j], sum[i+j-1] - sum[i-1]);
                }
            }
        }
        int ans = 0;
        for (int j = 1; j <= sqrt(2*n); j++) {
            if (dp[1][j]) ans = j;
        }
        cout << ans << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

F1. Korney Korneevich and XOR (easy version)

同样考虑dp

dp的状态还是很巧妙的,设 d p [ i ] dp[i] dp[i]表示构成i的当前最小值,两层for转移一下就行

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)
#define endl '\n'
int a[N];
int dp[N];
void solve() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= 1024; j++) {
            if (a[i] > dp[j]) {
                dp[j^a[i]] = min(dp[j^a[i]], a[i]);
            }
        }
    }
    vector<int> ans;
    for (int i = 0; i <= 1024; i++) if (dp[i] <= 500) ans.push_back(i);
    cout << ans.size() << endl;
    for (auto it : ans) cout << it << ' ';
    cout << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

赛后想到更直接的转移,利用线段树。

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

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 1e9 + 7;

#define fi first
#define se second
#define re register
#define lowbit (-x&x)
#define endl '\n'
int a[N];
struct Tree {
    int l, r;
    bitset<1024> f;
}t[505<<2];
void push_up(int u) {
    t[u].f = t[u<<1].f | t[u<<1|1].f;
}
void build(int u, int l, int r) {
    t[u].l = l, t[u].r = r;
    if (l == r) {
        if (l == 0) t[u].f[0] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(u<<1, l, mid);
    build(u<<1|1, mid+1, r);
    push_up(u);
}
void modify(int u, int pos, bitset<1024> val) {
    if (t[u].l == t[u].r) {
        t[u].f |= val;
        return;
    }
    int mid = (t[u].l + t[u].r) >> 1;
    if (pos <= mid) modify(u<<1, pos, val);
    else modify(u<<1|1, pos, val);
    push_up(u);
}
bitset<1024> query(int u, int ql, int qr) {
    if (ql <= t[u].l && qr >= t[u].r) return t[u].f;
    int mid = (t[u].l + t[u].r) >> 1;
    bitset<1024> ans;
    if (ql <= mid) ans |= query(u<<1, ql, qr);
    if (qr > mid) ans |= query(u<<1|1, ql, qr);
    return ans;
}
void solve() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    build(1, 0, 500);
    for (int i = 1; i <= n; i++) {
        if (!a[i]) continue;
        bitset<1024> now = query(1, 0, a[i]-1);
        for (int j = 0; j < 1024; j++) if (now[j]) now[j^a[i]]=1;
        modify(1, a[i], now);
    }
    cout << t[1].f.count() << endl;
    for (int i = 0; i < 1024; i++) if (t[1].f[i]) cout << i << ' ';
    cout << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif

#ifdef ACM_LOCAL
    auto start = clock();
#endif
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
#ifdef ACM_LOCAL
    auto end = clock();
    cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值