Codeforces Round #851 (Div. 2)(A~D)

A. One and Two

给出一个数组,该数组仅由1和2组成,问是否有最小的k使得k位置的前缀积和后缀积相等。

思路:计算2个数的前缀和即可,遍历判断。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
int t, n;
int a[N], pre[N];

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> n;
        for(int i = 1; i <= n; i ++) {
            std::cin >> a[i];
            if(a[i] == 2)
                pre[i] = pre[i - 1] + 1;
            else
                pre[i] = pre[i - 1];
        }
        int ans = -1;
        for(int i = 1; i <= n; i ++) {
            if(pre[i] == pre[n] - pre[i]) {
                ans = i;
                break;
            }
        }
        std::cout << ans << '\n';
    }
    return 0;
}

B. Sum of Two Numbers

给出一个数字n,求x和y,满足x+y=n,x和y的各位数之和相差不超过1。

思路:直接对于每一位均分即可。如果该位为奇数,1的个数交替给x和y。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
int t, n;
bool vis[15];

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> n;
        char a[15] = {0}, b[15] = {0}, cnta = 0, cntb = 0;
        memset(vis, 0, sizeof(vis));
        std::string s = std::to_string(n);
        for(int i = 0; i < s.length(); i ++) {
            int num = s[i] - '0';
            if(!(num & 1))
                a[cnta ++] = num / 2 + '0', b[cntb ++] = num / 2 + '0';
            else {
                vis[cnta] = 1;
                a[cnta ++] = num / 2 + '0', b[cntb ++] = num / 2 + '0';
            }
        }
        int pos = 0;
        for(int i = 0; i <= 15; i ++) {
            if(vis[i]) {
                if(pos)
                    a[i] = a[i] - '0' + 1 + '0';
                else
                    b[i] = b[i] - '0' + 1 + '0';
                pos ^= 1;
            }
        }
        int x = std::atoi(a), y = std::atoi(b);
        std::cout << x << ' ' << y << '\n';
    }
    return 0;
}

os:这个代码写的像shit一样。。。

C. Matching Numbers

给出1~2*n这些数,能否分成两两一组,使得每组的和是连续的数?

思路:很显然,n为偶数时,是不可以按要求分组的。n为奇数时,手摸几组样例可以知道,这个连续的数字是1+2*n-n/2 ~ 1+2*n+n/2,然后从大数开始,发现后n/2个数可以表示后n/2个和,下面n/2个数可以表示前n/2个和。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
typedef std::pair<int, int> PII;
const int N = 2e5 + 5;
int t, n;
bool vis[N];

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> n;
        if(!(n & 1)) {
            std::cout << "NO" << '\n';
            continue;
        }
        std::vector<PII> vec;
        vec.push_back({n, n + 1});
        int num = 2 + 2 * n;
        for(int i = n * 2; i >= 2 * n - n / 2 + 1; i --) {
            vec.push_back({i, num - i});
            num ++;
        }
        num = 1 + 2 * n - n / 2;
        for(int i = 2 * n - n / 2; i >= n + 2; i --) {
            vec.push_back({i, num - i});
            num  ++;
        }
        std::cout << "YES" << '\n';
        for(auto [x, y] : vec)
            std::cout << x << ' ' << y << '\n';
    }
    return 0;
}

D. Moving Dots

在一个数轴上有n个数,每个点都以相同的速度移动,若是左右两点的距离不同,向距离较小的点移动;若是相同,则向左移动。两个点移动到一起时,他们会停下。对于每个子序列,问剩下的点的和是多少。

思路:每一对点,它会有贡献的时候是他们两个向中间相向而行,最后汇聚成一个点。那么我们可以计算每一对点的贡献,在一个字序列中,这对点有贡献的时候是他们两个两侧没有相距更小而使得这一对点向背而行,其他的点任选即可,即2^n中选择方法。

学习大佬的思路

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 3e3 + 5;
const int mod = 1e9 + 7;
int n;
int a[N];

template<const int T>
struct ModInt {
    const static int mod = T;
    int x;
    ModInt(int x = 0) : x(x % mod) {}
    ModInt(ll x) : x(int(x % mod)) {} 
    int val() { return x; }
    ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
    ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
    ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
    ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
    void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
    void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
    void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
    void operator /= (const ModInt &a) { *this = *this / a; }
    friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x;}
    
    ModInt pow(int64_t n) const {
        ModInt res(1), mul(x);
        while(n){
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    
    ModInt inv() const {
        int a = x, b = mod, u = 1, v = 0;
        while (b) {
            int t = a / b;
            a -= t * b; std::swap(a, b);
            u -= t * v; std::swap(u, v);
        }
        if (u < 0) u += mod;
        return u;
    }
    
};
typedef ModInt<1000000007> mint;

mint pow2[N];

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> n;
    pow2[0] = 1;
    for(int i = 1; i <= n; i ++) {
        std::cin >> a[i];
        pow2[i] = pow2[i - 1] * 2;
    }
    mint ans = 0;
    for(int i = 1; i <= n; i ++) {
        for(int j = i + 1; j <= n; j ++) {
            int d = a[j] - a[i];
            int l = std::lower_bound(a + 1, a + 1 + n, a[i] - d) - a - 1;
            int r = std::lower_bound(a + 1, a + 1 + n, a[j] + d) - a;
            ans += pow2[l + n - r + 1];
        }
    }
    std::cout << ans << '\n';
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值