Codeforces Round #750 (Div. 2)题解

Codeforces Round #750 (Div. 2)

A. Luntik and Concerts

太傻逼了,就是sum判断&1。
比起这个,一开始ABC中出了BC卡A的我不是更傻逼…

#include <bits/stdc++.h>

typedef long long ll;
using namespace std;

int main() {
    int T;
    cin >> T;
    while (T--) {
        ll a, b, c;
        cin >> a >> b >> c;
        ll sum = a + b*2ll + c*3ll;
        if (sum & 1)
            cout << 1 << endl;
        else cout << 0 << endl;
    }
}

B. Luntik and Subsequences

就是问你存在几个子序列使得sum=sum源-1。
考虑0,1的数量即可。

#include <bits/stdc++.h>

typedef long long ll;
using namespace std;

int main() {
    int T;
    cin >> T;
    while (T--) {
        int n, x;
        cin>>n;
        int cnt0 = 0, cnt1 = 0;
        for (int i = 0; i < n; i++) {
            cin >> x;
            if (x == 0) cnt0++;
            if (x == 1) cnt1++;
        }
      //  cout << cnt1 << " " << cnt0 << endl;
        ll ans = cnt1 * (1ll << cnt0);
        cout << ans << endl;
    }
}

C. Grandma Capa Knits a Scarf

意思是说给你一个字符串,只能揪着相同的一个字母去掉,变成回文串,问最少改动的方案改动几个。

我觉得还是很巧妙的,枚举改动哪个字母,然后两端开始枚举,肯定是要一样的,如果不一样且刚好有一个字母是可以改的就改掉再看一不一样,出现两端都不能改就寄了。

双指针写的有些丑陋。

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
vector<int> v;

int main() {
    int T;
    cin >> T;
    while (T--) {
        v.clear();
        int n;
        cin >> n;
        string s;
        cin >> s;
        // cout << s << endl;
        int ans;
        int f = 0;
        int ff = 0;
        for (char c = 'a'; c <= 'z'; c++) {
            f = 0;
            ans = 0;
            int l = 0, r = n - 1;
            while (l < r) {
                if (s[l] != s[r]) {
                    if (s[l] == c) l++, ans++;
                    else if (s[r] == c) r--, ans++;
                    else {
                        f = 1;
                        break;
                    }
                } else {
                    l++;
                    r--;
                }
            }
            if (!f) {
                v.push_back(ans);
                ff = 1;
            }
        }
        if (!ff) {
            cout << -1 << endl;
            continue;
        }
        sort(v.begin(), v.end());
        cout << v[0] << endl;
    }
}

D. Vupsen, Pupsen and 0

给你一个数组a,意思要你构造一个数组b,实现 ∑ b i ∗ a i = = 0 。 ∑b_i*a_i==0。 biai==0然后保证b数组求和小于1e9。

这东西,偶数个的时候很好构造,两两交叉取反,不放心就GCD一下。
b i = − a j , b j = − a i b_i=-a_j,b_j=-a_i bi=aj,bj=ai
奇数的话,先整3个处理一下保证这三个满足条件,后面参照偶数处理方法。
b 1 = − a 3 , b 2 = − a 3 , b 3 = ( a 1 + a 2 ) b_1=-a_3,b_2=-a_3,b_3=(a_1+a_2) b1=a3,b2=a3,b3=(a1+a2)
注意b数组都不能有0,所以小心 b 3 = ( a 1 + a 2 ) = 0 b_3=(a_1+a_2)=0 b3=(a1+a2)=0
所以要这样套三次,不可能 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3三个数全部两两和为0,总有一种方法可以成功处理这三个数。

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int a[114514];
vector<int> ans;

int main() {
    int T;
    cin >> T;
    while (T--) {
        ans.clear();
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        if (n & 1) {
            if ((a[1] + a[2])!=0) {
            //不能if(a[1]+a[2])
                ans.push_back(-a[3]);
                ans.push_back(-a[3]);
                ans.push_back(a[2] + a[1]);
            } else if ((a[2] + a[3])!=0) {
                ans.push_back(a[2] + a[3]);
                ans.push_back(-a[1]);
                ans.push_back(-a[1]);
            } else if ((a[1] + a[3])!=0) {
                ans.push_back(-a[2]);
                ans.push_back(a[1] + a[3]);
                ans.push_back(-a[2]);
            }
            for (int i = 4; i <= n; i += 2) {
                int tt = __gcd(a[i + 1], a[i]);
                ans.push_back(a[i + 1] / tt);
                ans.push_back(-a[i] / tt);
            }
        } else {
            for (int i = 1; i <= n; i += 2) {
                int tt = __gcd(a[i + 1], a[i]);
                ans.push_back(a[i + 1] / tt);
                ans.push_back(-a[i] / tt);
            }
        }
        for (auto i:ans) {
            cout << i << " ";
        }
        cout << endl;
        memset(a, 0, sizeof(a));
    }
}

F1. Korney Korneevich and XOR (easy version)

在给定序列里,找严格递增子序列取中间的数字xor,问有几个不同的答案。

在这里插入图片描述
品品这个范围,其实xor结果最多到512。
定义dp式子如下:
d p [ i ] = x ; dp[i]=x; dp[i]=x;
xor结果为i的严格递增子序列中,最大的数字是x。

思路就是:其实对于结果相同的严格递增子序列,只要记最大数最小的即可,因为如果要更新的话,这样的情况,可选下一个数字的范围更大。

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
using namespace std;
int dp[600];
vector<int> ans;

int main() {
    memset(dp, INF, sizeof(dp));
    int n;
    cin >> n;
    int x;
    for (int i = 0; i < n; i++) {
        cin >> x;
        dp[x] = min(x, dp[x]);
        for (int j = 0; j <= 512; j++) {
            if (x >= dp[j])
                dp[j ^ x] = min(dp[j ^ x], x);
        }
    }
    for (int i = 0; i <= 512; i++) {
        if (dp[i] != INF) ans.push_back(i);
    }
    cout << ans.size() << endl;
    for (auto i:ans) {
        cout << i << " ";
    }
}

error代码,不知道为啥T8了,绷不住了,到底哪里特别慢了啊…还是STL的问题?

#include <bits/stdc++.h>

using namespace std;
int dp[600];
set<int> ans;

int main() {
    memset(dp, -1, sizeof(dp));
    int n;
    cin >> n;
    int x;
    for (int i = 0; i < n; i++) {
        cin >> x;
        if (dp[x] == -1)
            dp[x] = x;
        else
            dp[x] = min(dp[x], x);
        ans.insert(x);
        for (int j = 0; j <= 512; j++) {
            if (x >= dp[j] && dp[j] != -1) {
                if (dp[j ^ x] != -1)dp[j ^ x] = min(dp[j ^ x], x);
                else dp[j ^ x] = x;
                ans.insert((j ^ x));
            }
        }

    }
    cout << ans.size() << '\n';
    for (auto i:ans) {
        cout << i << " ";
    }
}

以后这种转移用 m i n min min的还是初始化0x3f3f3f3f好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值