Codeforces#435

比赛地址:Codeforces Round #435 (Div. 2)
  这场的题目都挺有意思的!

C. Mahmoud and Ehab and the xor

题意:
  给定n与x,求n个不同的数,使它们异或之后等于x。
题解:

  1. 当n==2,x==0的时候无解
  2. 构造:
    1. pp = 1<<17;
    2. 构造1、2、…、n-3,异或值为y
    3. 如果x^y==0,那么构造pp,pp*2,pp^(pp*2)
    4. 如果x^y!=0,那么构造0,pp,pp^(x^y)

代码:

#include<iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;

int main() {
    int n, x;
    cin >> n >> x;
    if (n == 2 && x == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        if (n == 1) {
            cout << x << endl;
        }
        else if (n == 2) {
            cout << 0 << " " << x << endl;
        }
        else {
            int temp = 0;
            int pp = 1 << 17;
            for (int i = 0; i < n - 3; i++) {
                cout << i + 1 << " ";
                temp ^= (i + 1);
            }
            if (temp == x) {
                cout << pp << " " << pp * 2 << " " << ((pp)^(pp * 2)) << endl;
            }
            else {
                cout << 0 << " " << pp << " " << (pp ^ (x ^ temp)) << endl;
            }
        }
    }
    return 0;
}

D. Mahmoud and Ehab and the binary string

题意:
  现在Evi有一个长度为n的隐藏字符串x(一定有一个1和一个0),现在你可以询问Evi,你给一个长度为n的字符串y,那么他会告诉你x与y有多少位不同。
  现在告诉你长度n,你必须在15次询问之内,确定x中一个1和一个0的位置。
题解:
  那么我们首先用一个全是0的字符串去询问,那么返回值num就是字符串中1的个数。
  然后呢,因为原字符串中一定有一个1和一个0,并且又全部由1和0组成,那么一定能找到一个相邻位置l和r,他们是01或者10,那么我们用二分法来找这个l和r.
  首先令l == 0 , r == N-1
  那么我们判断一下[mid,r]中是否全是1或者0
  怎么判断呢,我们这个时候用一个0–(mid-1)全是0,mid–r全是1,r–N-1全是0的串去询问,如果结果为num-(r-l+1)那么[mid,r]中是否全是1,如果结果为num+(r-l+1)那么[mid,r]中是否全是0,这种情况另r=mid。否则这中间既有1又有0,另l=mid.
  那么二分策略就出来了。
代码:

#include<iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;

int N, num;

bool check(int l, int r) {
    cout << "? ";
    for (int i = 0; i < l; i++) {
        cout << "0";
    }
    for (int i = l; i <= r; i++) {
        cout << "1";
    }
    for (int i = r + 1; i < N; i++) {
        cout << "0";
    }
    puts("");
    fflush(stdout);
    int temp;
    cin >> temp;
    if (temp > num - (r - l + 1) && temp < num + (r - l + 1)) {
        return true;
    }
    else {
        return false;
    }
}

int main() {

    cin >> N;
    cout << "? ";
    for (int i = 0; i < N; i++) {
        cout << "0";
    }
    puts("");
    fflush(stdout);
    cin >> num;
    int l = 0, r = N - 1;
    while (r > l + 1) {
        int mid = (l + r) / 2;
        if (check(mid, r)) {
            l = mid;
        }
        else {
            r = mid;
        }
    }
    cout << "? ";
    for (int i = 0; i < l; i++) {
        cout << "0";
    }
    for (int i = l; i < r; i++) {
        cout << "1";
    }
    for (int i = r; i < N; i++) {
        cout << "0";
    }
    puts("");
    fflush(stdout);
    int temp;
    cin >> temp;
    if (temp > num ) {
        cout << "! " << l + 1 << " " << r + 1 << endl;
    }
    else {
        cout << "! " << r + 1 << " " << l + 1 << endl;
    }
    return 0;
}

E. Mahmoud and Ehab and the function

题意:
  略。。。
题解:
  推推公式,每次二分找一下就是的,太简单。
代码:

#include<iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;

long long a[100010], b[100010];
long long n, m, q;
long long sum[100010];
long long cnt1, cnt2;

long long get(int l, int r, long long val) {
    if ((r - l + 1) & 1) {
        if (l & 1) {
            cnt1 += val;
        }
        else {
            cnt1 -= val;
        }
    }
    long long* pos = upper_bound(sum, sum + m - n + 1, -cnt1);
    long long ans;
    if (pos >= sum + m - n + 1) {
        pos--;
        ans = abs(*pos + cnt1);
    }
    else if (pos == sum) {
        ans = abs(*pos + cnt1);
    }
    else {
        ans = abs(*pos + cnt1);
        pos--;
        ans = min(ans, abs(*pos + cnt1));
    }
    return ans;
}

int main() {
    cin >> n >> m >> q;

    cnt1 = cnt2 = 0;
    int f = 1;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        cnt1 += f * a[i];
        f *= -1;
    }
    for (int i = 1; i <= m; i++) {
        cin >> b[i];
        if (i <= n) {
            if (i & 1) {
                cnt2 -= b[i];
            }
            else {
                cnt2 += b[i];
            }
        }
    }
    sum[0] = cnt2;
    for (int i = n + 1; i <= m; i++) {
        cnt2 += b[i - n];
        cnt2 *= -1;
        if (n & 1) {
            cnt2 -= b[i];
        }else{
            cnt2 += b[i];
        }
        sum[i - n] = cnt2;
    }
    sort(sum, sum + m - n + 1);
    cout << get(1, 1, 0) << endl;
    for (int i = 0; i < q; i++) {
        int l, r, x;
        cin >> l >> r >> x;

        cout << get(l,r,x) << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值